Coverage Report

Created: 2026-08-31 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/src/server/ua_services_session.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-2017 (c) Florian Palm
7
 *    Copyright 2014-2016 (c) Sten Grüner
8
 *    Copyright 2015 (c) Chris Iatrou
9
 *    Copyright 2015 (c) Oleksiy Vasylyev
10
 *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
11
 *    Copyright 2017-2018 (c) Mark Giraud, Fraunhofer IOSB
12
 *    Copyright 2019 (c) Kalycito Infotech Private Limited
13
 *    Copyright 2018-2020 (c) HMS Industrial Networks AB (Author: Jonas Green)
14
 *    Copyright 2025 (c) Siemens AG (Author: Tin Raic)
15
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Julius Pfrommer)
16
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Andreas Ebner)
17
 */
18
19
#include "ua_server_internal.h"
20
#include "ua_services.h"
21
22
void
23
notifySession(UA_Server *server, UA_Session *session,
24
13.3k
              UA_ApplicationNotificationType type) {
25
    /* Nothing to do */
26
13.3k
    if(!server->config.globalNotificationCallback &&
27
13.3k
       !server->config.sessionNotificationCallback)
28
13.3k
        return;
29
30
    /* Set up the payload */
31
0
    size_t payloadSize = 6 + session->attributes.mapSize;
32
0
    UA_STACKARRAY(UA_KeyValuePair, payloadData, payloadSize);
33
0
    UA_KeyValueMap payloadMap = {payloadSize, payloadData};
34
0
    payloadData[0].key = UA_QUALIFIEDNAME(0, "session-id");
35
0
    UA_Variant_setScalar(&payloadData[0].value, &session->sessionId,
36
0
                         &UA_TYPES[UA_TYPES_NODEID]);
37
0
    payloadData[1].key = UA_QUALIFIEDNAME(0, "securechannel-id");
38
0
    UA_UInt32 secureChannelId = 0;
39
0
    if(session->channel)
40
0
        secureChannelId = session->channel->securityToken.channelId;
41
0
    UA_Variant_setScalar(&payloadData[1].value, &secureChannelId,
42
0
                         &UA_TYPES[UA_TYPES_UINT32]);
43
0
    payloadData[2].key = UA_QUALIFIEDNAME(0, "session-name");
44
0
    UA_Variant_setScalar(&payloadData[2].value, &session->sessionName,
45
0
                         &UA_TYPES[UA_TYPES_STRING]);
46
0
    payloadData[3].key = UA_QUALIFIEDNAME(0, "client-description");
47
0
    UA_Variant_setScalar(&payloadData[3].value, &session->clientDescription,
48
0
                         &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]);
49
0
    payloadData[4].key = UA_QUALIFIEDNAME(0, "client-user-id");
50
0
    UA_Variant_setScalar(&payloadData[4].value, &session->clientUserIdOfSession,
51
0
                         &UA_TYPES[UA_TYPES_STRING]);
52
0
    payloadData[5].key = UA_QUALIFIEDNAME(0, "locale-ids");
53
0
    UA_Variant_setArray(&payloadData[5].value, session->localeIds,
54
0
                        session->localeIdsSize, &UA_TYPES[UA_TYPES_STRING]);
55
56
0
    if(session->attributes.mapSize)
57
0
        memcpy(&payloadData[6], session->attributes.map,
58
0
               sizeof(UA_KeyValuePair) * session->attributes.mapSize);
59
60
    /* Call the notification callback */
61
0
    if(server->config.sessionNotificationCallback)
62
0
        server->config.sessionNotificationCallback(server, type, payloadMap);
63
0
    if(server->config.globalNotificationCallback)
64
0
        server->config.globalNotificationCallback(server, type, payloadMap);
65
0
}
66
67
/* Delayed callback to free the session memory */
68
static void
69
9.21k
removeSessionCallback(UA_Server *server, session_list_entry *entry) {
70
9.21k
    lockServer(server);
71
9.21k
    UA_Session_clear(&entry->session, server);
72
9.21k
    unlockServer(server);
73
9.21k
    UA_free(entry);
74
9.21k
}
75
76
void
77
UA_Session_remove(UA_Server *server, UA_Session *session,
78
9.21k
                  UA_ShutdownReason shutdownReason) {
79
9.21k
    UA_LOCK_ASSERT(&server->serviceMutex);
80
81
    /* When the session times out, detach
82
     * subscriptions so they can be recovered via TransferSubscriptions. */
83
9.21k
#ifdef UA_ENABLE_SUBSCRIPTIONS
84
9.21k
    UA_Subscription *sub, *tempsub;
85
9.21k
    TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, tempsub) {
86
0
        if(shutdownReason == UA_SHUTDOWNREASON_TIMEOUT) {
87
0
            UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub,
88
0
                                     "Detaching the Subscription from the timed-out Session");
89
0
            UA_Session_detachSubscription(server, session, sub, true);
90
0
        } else {
91
0
            UA_Subscription_delete(server, sub);
92
0
        }
93
0
    }
94
95
9.21k
    UA_PublishResponseEntry *entry;
96
9.21k
    while((entry = UA_Session_dequeuePublishReq(session))) {
97
0
        UA_PublishResponse_clear(&entry->response);
98
0
        UA_free(entry);
99
0
    }
100
9.21k
#endif
101
102
    /* Callback into userland access control */
103
9.21k
    if(server->config.accessControl.closeSession) {
104
9.21k
        server->config.accessControl.
105
9.21k
            closeSession(server, &server->config.accessControl,
106
9.21k
                         &session->sessionId, session->context);
107
9.21k
    }
108
109
    /* Detach the Session from the SecureChannel */
110
9.21k
    UA_Session_detachFromSecureChannel(server, session);
111
112
    /* Deactivate the session */
113
9.21k
    if(session->activated) {
114
1.66k
        session->activated = false;
115
1.66k
        server->activeSessionCount--;
116
1.66k
    }
117
118
    /* Detach the session from the session manager and make the capacity
119
     * available */
120
9.21k
    session_list_entry *sentry = container_of(session, session_list_entry, session);
121
9.21k
    LIST_REMOVE(sentry, pointers);
122
9.21k
    server->sessionCount--;
123
124
9.21k
    switch(shutdownReason) {
125
9.04k
    case UA_SHUTDOWNREASON_CLOSE:
126
9.04k
    case UA_SHUTDOWNREASON_PURGE:
127
9.04k
        break;
128
0
    case UA_SHUTDOWNREASON_TIMEOUT:
129
0
        server->serverDiagnosticsSummary.sessionTimeoutCount++;
130
0
        break;
131
0
    case UA_SHUTDOWNREASON_REJECT:
132
0
        server->serverDiagnosticsSummary.rejectedSessionCount++;
133
0
        break;
134
0
    case UA_SHUTDOWNREASON_SECURITYREJECT:
135
0
        server->serverDiagnosticsSummary.securityRejectedSessionCount++;
136
0
        break;
137
171
    case UA_SHUTDOWNREASON_ABORT:
138
171
        server->serverDiagnosticsSummary.sessionAbortCount++;
139
171
        break;
140
0
    default:
141
0
        UA_assert(false);
142
0
        break;
143
9.21k
    }
144
145
    /* Notify the application */
146
9.21k
    notifySession(server, session, UA_APPLICATIONNOTIFICATIONTYPE_SESSION_CLOSED);
147
148
    /* Add a delayed callback to remove the session when the currently
149
     * scheduled jobs have completed */
150
9.21k
    sentry->cleanupCallback.callback = (UA_Callback)removeSessionCallback;
151
9.21k
    sentry->cleanupCallback.application = server;
152
9.21k
    sentry->cleanupCallback.context = sentry;
153
9.21k
    UA_EventLoop *el = server->config.eventLoop;
154
9.21k
    el->addDelayedCallback(el, &sentry->cleanupCallback);
155
9.21k
}
156
157
void
158
0
cleanupSessions(UA_Server *server, UA_DateTime nowMonotonic) {
159
0
    UA_LOCK_ASSERT(&server->serviceMutex);
160
0
    session_list_entry *sentry, *temp;
161
0
    LIST_FOREACH_SAFE(sentry, &server->sessions, pointers, temp) {
162
        /* Session has timed out? */
163
0
        if(sentry->session.validTill >= nowMonotonic)
164
0
            continue;
165
0
        UA_LOG_INFO_SESSION(server->config.logging, &sentry->session,
166
0
                            "Session has timed out");
167
0
        UA_Session_remove(server, &sentry->session, UA_SHUTDOWNREASON_TIMEOUT);
168
0
    }
169
0
}
170
171
/************/
172
/* Services */
173
/************/
174
175
UA_Session *
176
3.41k
getSessionByToken(UA_Server *server, const UA_NodeId *token) {
177
3.41k
    UA_LOCK_ASSERT(&server->serviceMutex);
178
179
3.41k
    session_list_entry *current = NULL;
180
3.78k
    LIST_FOREACH(current, &server->sessions, pointers) {
181
        /* Token does not match */
182
3.78k
        if(!UA_NodeId_equal(&current->session.authenticationToken, token))
183
2.60k
            continue;
184
185
        /* Session has timed out */
186
1.18k
        UA_EventLoop *el = server->config.eventLoop;
187
1.18k
        UA_DateTime now = el->dateTime_nowMonotonic(el);
188
1.18k
        if(now > current->session.validTill) {
189
40
            UA_LOG_WARNING_SESSION(server->config.logging, &current->session,
190
40
                                   "Client tries to use a session that has timed out");
191
40
            return NULL;
192
40
        }
193
194
1.14k
        return &current->session;
195
1.18k
    }
196
197
2.23k
    return NULL;
198
3.41k
}
199
200
UA_Session *
201
2.36k
getSessionById(UA_Server *server, const UA_NodeId *sessionId) {
202
2.36k
    UA_LOCK_ASSERT(&server->serviceMutex);
203
204
    /* A NULL sessionId is a programming error from the public API
205
     * (UA_Server_closeSession) or from an internal caller that has
206
     * no session id. Treat it as "not found" so callers like
207
     * UA_Server_closeSession can return BADSESSIONIDINVALID instead
208
     * of dereferencing NULL inside UA_NodeId_equal. */
209
2.36k
    if(!sessionId)
210
0
        return NULL;
211
212
2.36k
    session_list_entry *current = NULL;
213
2.36k
    LIST_FOREACH(current, &server->sessions, pointers) {
214
        /* Token does not match */
215
2.36k
        if(!UA_NodeId_equal(&current->session.sessionId, sessionId))
216
0
            continue;
217
218
        /* Session has timed out */
219
2.36k
        UA_EventLoop *el = server->config.eventLoop;
220
2.36k
        UA_DateTime now = el->dateTime_nowMonotonic(el);
221
2.36k
        if(now > current->session.validTill) {
222
0
            UA_LOG_WARNING_SESSION(server->config.logging, &current->session,
223
0
                                   "Client tries to use a session that has timed out");
224
0
            return NULL;
225
0
        }
226
227
2.36k
        return &current->session;
228
2.36k
    }
229
230
0
    if(UA_NodeId_equal(sessionId, &server->adminSession.sessionId))
231
0
        return &server->adminSession;
232
233
0
    return NULL;
234
0
}
235
236
static UA_StatusCode
237
signCreateSessionResponse(UA_Server *server, UA_SecureChannel *channel,
238
                          const UA_CreateSessionRequest *request,
239
4.06k
                          UA_CreateSessionResponse *response) {
240
4.06k
    if(channel->securityMode != UA_MESSAGESECURITYMODE_SIGN &&
241
4.06k
       channel->securityMode != UA_MESSAGESECURITYMODE_SIGNANDENCRYPT)
242
4.06k
        return UA_STATUSCODE_GOOD;
243
244
0
    const UA_SecurityPolicy *sp = channel->securityPolicy;
245
0
    void *cc = channel->channelContext;
246
0
    UA_SignatureData *signatureData = &response->serverSignature;
247
248
    /* Prepare the signature */
249
0
    const UA_SecurityPolicySignatureAlgorithm *signAlg = &sp->asymSignatureAlgorithm;
250
0
    size_t signatureSize = signAlg->getLocalSignatureSize(sp, cc);
251
0
    UA_StatusCode retval = UA_STATUSCODE_GOOD;
252
    /* OPC UA Part 4 v1.05.07: for SecurityPolicies with
253
     * secureChannelEnhancements = true, the algorithm field in
254
     * SignatureData shall be NULL or empty and receivers shall
255
     * ignore the value. */
256
0
    if(!UA_SecurityPolicy_isEnhancedSecurity(sp))
257
0
        retval = UA_String_copy(&signAlg->uri, &signatureData->algorithm);
258
0
    retval |= UA_ByteString_allocBuffer(&signatureData->signature, signatureSize);
259
0
    if(retval != UA_STATUSCODE_GOOD)
260
0
        return retval;
261
262
    /* Build the data to sign. */
263
0
    UA_ByteString dataToSign = UA_BYTESTRING_NULL;
264
0
    if(UA_SecurityPolicy_isEnhancedSecurity(sp)) {
265
        /* Channel-bound v1.05.07 signature (see the cert-role table at
266
         * UA_SecureChannel_buildCreateSessionSignatureData). */
267
0
        retval = UA_SecureChannel_buildCreateSessionSignatureData(
268
0
            channel, &request->clientNonce, &response->serverNonce,
269
0
            &sp->localCertificate, &channel->remoteCertificate, &dataToSign);
270
0
    } else {
271
0
        retval = UA_ByteString_allocBuffer(&dataToSign,
272
0
            request->clientCertificate.length + request->clientNonce.length);
273
0
        if(retval == UA_STATUSCODE_GOOD) {
274
0
            memcpy(dataToSign.data, request->clientCertificate.data,
275
0
                   request->clientCertificate.length);
276
0
            memcpy(dataToSign.data + request->clientCertificate.length,
277
0
                   request->clientNonce.data, request->clientNonce.length);
278
0
        }
279
0
    }
280
0
    if(retval != UA_STATUSCODE_GOOD)
281
0
        return retval; /* signatureData->signature is cleaned up with the response */
282
283
0
    retval = signAlg->sign(sp, cc, &dataToSign, &signatureData->signature);
284
285
    /* Clean up */
286
0
    UA_ByteString_clear(&dataToSign);
287
0
    return retval;
288
0
}
289
290
static UA_StatusCode
291
createCheckSessionAuthSecurityPolicyContext(UA_Server *server, UA_Session *session,
292
                                            UA_SecurityPolicy *sp, const char *logPrefix,
293
0
                                            const UA_ByteString remoteCertificate) {
294
    /* The session is already "taken" by a different SecurityPolicy */
295
0
    if(session->sessionSp && session->sessionSp != sp) {
296
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
297
0
                             "%s: Cannot instantiate SecurityPolicyContext %S for the "
298
0
                             "Session. A different SecurityPolicy %S is "
299
0
                             "already in place", logPrefix, sp->policyUri,
300
0
                             session->sessionSp->policyUri);
301
0
        return UA_STATUSCODE_BADSECURITYPOLICYREJECTED;
302
0
    }
303
0
    session->sessionSp = sp;
304
305
    /* Existing SecurityPolicy context, check for the identical remote
306
     * certificate */
307
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
308
0
    if(session->sessionSpContext) {
309
0
        res = sp->compareCertificate(sp, session->sessionSpContext, &remoteCertificate);
310
0
        if(res != UA_STATUSCODE_GOOD) {
311
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
312
0
                                 "%s: The client tries to use a different certificate "
313
0
                                 "for authentication", logPrefix);
314
0
        }
315
0
        return res;
316
0
    }
317
318
    /* Instantiate a new context if we can. Otherwise operate without a channel
319
     * context. That is possible for asymmetric decryption with RSA which
320
     * requires only the local certificate. But ECC won't work. */
321
0
    if(remoteCertificate.length > 0) {
322
0
        res = sp->newChannelContext(sp, &remoteCertificate,
323
0
                                    &session->sessionSpContext);
324
0
        if(res != UA_STATUSCODE_GOOD) {
325
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
326
0
                                 "%s: Could not use the supplied certificate "
327
0
                                 "to instantiate the SecurityPolicy %S for the "
328
0
                                 "validation of the UserIdentityToken",
329
0
                                 logPrefix, sp->policyUri);
330
0
        }
331
0
    }
332
0
    return res;
333
0
}
334
335
/* The client requests a server ephemeral ECDH key by adding an "ECDHPolicyUri"
336
 * entry to the request's AdditionalHeader (an AdditionalParametersType). The
337
 * server must return its ECDHKey only when this was requested. */
338
static UA_Boolean
339
0
clientRequestedEphemeralKey(const UA_ExtensionObject *additionalHeader) {
340
0
    if(additionalHeader->encoding != UA_EXTENSIONOBJECT_DECODED &&
341
0
       additionalHeader->encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE)
342
0
        return false;
343
0
    if(additionalHeader->content.decoded.type !=
344
0
       &UA_TYPES[UA_TYPES_ADDITIONALPARAMETERSTYPE])
345
0
        return false;
346
0
    const UA_AdditionalParametersType *ap = (const UA_AdditionalParametersType*)
347
0
        additionalHeader->content.decoded.data;
348
0
    UA_String ecdhPolicyUri = UA_STRING("ECDHPolicyUri");
349
0
    for(size_t i = 0; i < ap->parametersSize; i++) {
350
0
        if(ap->parameters[i].key.namespaceIndex == 0 &&
351
0
           UA_String_equal(&ap->parameters[i].key.name, &ecdhPolicyUri))
352
0
            return true;
353
0
    }
354
0
    return false;
355
0
}
356
357
static UA_StatusCode
358
addEphemeralKeyAdditionalHeader(UA_Server *server, UA_Session *session,
359
0
                                UA_ExtensionObject *ah) {
360
0
    UA_assert(session->sessionSp && session->sessionSpContext);
361
0
    UA_SecurityPolicy *sp = session->sessionSp;
362
0
    void *spContext = session->sessionSpContext;
363
364
    /* Allocate additional parameters */
365
0
    UA_AdditionalParametersType *ap = UA_AdditionalParametersType_new();
366
0
    if(!ap)
367
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
368
369
    /* Set the additional parameters in the additional header. They also get
370
     * cleaned up from there in the error case. */
371
0
    UA_ExtensionObject_setValue(ah, ap, &UA_TYPES[UA_TYPES_ADDITIONALPARAMETERSTYPE]);
372
373
    /* UA_KeyValueMap has the identical layout. And better helper methods. */
374
0
    UA_KeyValueMap *map = (UA_KeyValueMap*)ap;
375
376
    /* Add the PolicyUri to the map */
377
0
    UA_StatusCode res =
378
0
        UA_KeyValueMap_setScalar(map, UA_QUALIFIEDNAME(0, "ECDHPolicyUri"),
379
0
                                 &sp->policyUri, &UA_TYPES[UA_TYPES_STRING]);
380
0
    if(res != UA_STATUSCODE_GOOD)
381
0
        return res;
382
383
    /* Initialize the EphemeralKey on the stack */
384
0
    UA_EphemeralKeyType ephKey;
385
0
    UA_EphemeralKeyType_init(&ephKey);
386
387
    /* Allocate the ephemeral key buffer to the exact size of the ephemeral key
388
     * for the used ECC policy so that the nonce generation function knows that
389
     * it needs to generate an ephemeral key and not some other random byte
390
     * string.
391
     *
392
     * TODO: There should be a more stable way to signal the generation of an
393
     * ephemeral key */
394
0
    res = UA_ByteString_allocBuffer(&ephKey.publicKey, sp->nonceLength);
395
0
    if(res != UA_STATUSCODE_GOOD)
396
0
        return res;
397
398
    /* Allocate the signature buffer */
399
0
    size_t signatureSize =
400
0
        sp->asymSignatureAlgorithm.getLocalSignatureSize(sp, spContext);
401
0
    res = UA_ByteString_allocBuffer(&ephKey.signature, signatureSize);
402
0
    if(res != UA_STATUSCODE_GOOD) {
403
0
        UA_EphemeralKeyType_clear(&ephKey);
404
0
        return res;
405
0
    }
406
407
    /* Generate the ephemeral key and signature */
408
0
    ephKey.publicKey.data[0] = 'e';
409
0
    ephKey.publicKey.data[1] = 'p';
410
0
    ephKey.publicKey.data[2] = 'h';
411
0
    res |= sp->generateNonce(sp, spContext, &ephKey.publicKey);
412
0
    res |= sp->asymSignatureAlgorithm.sign(sp, spContext, &ephKey.publicKey,
413
0
                                           &ephKey.signature);
414
415
    /* Add the EphemeralKey to the map (deep copy) */
416
0
    if(res == UA_STATUSCODE_GOOD)
417
0
        res = UA_KeyValueMap_setScalar(map, UA_QUALIFIEDNAME(0, "ECDHKey"),
418
0
                                       &ephKey, &UA_TYPES[UA_TYPES_EPHEMERALKEYTYPE]);
419
0
    UA_EphemeralKeyType_clear(&ephKey);
420
0
    return res;
421
0
}
422
423
/* Creates and adds a session. But it is not yet attached to a secure channel. */
424
UA_StatusCode
425
UA_Session_create(UA_Server *server, UA_SecureChannel *channel,
426
4.06k
                  const UA_CreateSessionRequest *request, UA_Session **session) {
427
4.06k
    UA_LOCK_ASSERT(&server->serviceMutex);
428
429
4.06k
    if(server->sessionCount >= server->config.maxSessions) {
430
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
431
0
                             "CreateSession: Could not create a Session - "
432
0
                             "Server limits reached");
433
0
        return UA_STATUSCODE_BADTOOMANYSESSIONS;
434
0
    }
435
436
4.06k
    session_list_entry *newentry = (session_list_entry*)
437
4.06k
        UA_malloc(sizeof(session_list_entry));
438
4.06k
    if(!newentry)
439
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
440
441
    /* Initialize the Session */
442
4.06k
    UA_Session_init(&newentry->session);
443
4.06k
    newentry->session.sessionId = UA_NODEID_GUID(1, UA_Guid_random());
444
4.06k
    newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random());
445
446
4.06k
    newentry->session.timeout = server->config.maxSessionTimeout;
447
4.06k
    if(request->requestedSessionTimeout <= server->config.maxSessionTimeout &&
448
2.86k
       request->requestedSessionTimeout > 0)
449
1.21k
        newentry->session.timeout = request->requestedSessionTimeout;
450
451
    /* Attach the session to the channel. But don't activate for now. */
452
4.06k
    if(channel)
453
4.06k
        UA_Session_attachToSecureChannel(server, &newentry->session, channel);
454
455
4.06k
    UA_EventLoop *el = server->config.eventLoop;
456
4.06k
    UA_DateTime now = el->dateTime_now(el);
457
4.06k
    UA_DateTime nowMonotonic = el->dateTime_nowMonotonic(el);
458
4.06k
    UA_Session_updateLifetime(&newentry->session, now, nowMonotonic);
459
460
    /* Add to the server */
461
4.06k
    LIST_INSERT_HEAD(&server->sessions, newentry, pointers);
462
4.06k
    server->sessionCount++;
463
464
    /* Notify the application */
465
4.06k
    notifySession(server, &newentry->session,
466
4.06k
                  UA_APPLICATIONNOTIFICATIONTYPE_SESSION_CREATED);
467
468
    /* Return */
469
4.06k
    *session = &newentry->session;
470
4.06k
    return UA_STATUSCODE_GOOD;
471
4.06k
}
472
473
void
474
Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
475
                      const UA_CreateSessionRequest *request,
476
4.06k
                      UA_CreateSessionResponse *response) {
477
4.06k
    UA_LOCK_ASSERT(&server->serviceMutex);
478
4.06k
    UA_LOG_DEBUG_CHANNEL(server->config.logging, channel, "CreateSession");
479
480
4.06k
    void *cc = channel->channelContext;
481
4.06k
    UA_SecurityPolicy *sp = channel->securityPolicy;
482
4.06k
    UA_ResponseHeader *rh = &response->responseHeader;
483
4.06k
    UA_assert(sp != NULL);
484
485
    /* Part 4: In many cases, the Certificates used to establish the
486
     * SecureChannel will be the ApplicationInstanceCertificates. However, some
487
     * Communication Stacks might not support Certificates that are specific to
488
     * a single application. Instead, they expect all communication to be
489
     * secured with a Certificate specific to a user or the entire machine. For
490
     * this reason, OPC UA Applications will need to exchange their
491
     * ApplicationInstanceCertificates when creating a Session.
492
     *
493
     * However Part 6 requires that the asymmetric algorithm security header
494
     * contains the "X.509 v3 Certificate assigned to the sending application
495
     * Instance." So we assume that the SecureChannel was created with the same
496
     * ApplicationInstanceCertificate. This may change in the future for
497
     * additional transport types. */
498
4.06k
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
499
4.06k
       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
500
501
        /* Compare the clientCertificate with the remoteCertificate of the
502
         * channel.
503
         *
504
         * Both the clientCertificate of this request and the remoteCertificate
505
         * of the channel may contain a partial or a complete certificate chain.
506
         * The compareCertificate function will compare the first certificate of
507
         * each chain. The end certificate shall be located first in the chain
508
         * according to the OPC UA specification Part 6 (1.04), chapter 6.2.3.*/
509
0
        UA_StatusCode res = sp->compareCertificate(sp, cc, &request->clientCertificate);
510
0
        if(res != UA_STATUSCODE_GOOD) {
511
0
            UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
512
0
                                 "CreateSession: The client uses a different "
513
0
                                 "certificate for SecureChannel and Session");
514
0
            server->serverDiagnosticsSummary.securityRejectedSessionCount++;
515
0
            server->serverDiagnosticsSummary.rejectedSessionCount++;
516
0
            rh->serviceResult = UA_STATUSCODE_BADCERTIFICATEINVALID;
517
0
            return;
518
0
        }
519
0
    }
520
521
    /* Check the client certificate and ApplicationDescription. It was already
522
     * checked for the SecureChannel. But here we use the Session
523
     * CertificateGroup and we now also have the ApplicationDescription to check
524
     * the ApplicationUri.
525
     *
526
     * Per OPC UA Part 4, Section 5.6.2.2: "If the securityPolicyUri is None,
527
     * the Server shall ignore the ApplicationInstanceCertificate." */
528
4.06k
    if(channel->securityPolicy->policyType == UA_SECURITYPOLICYTYPE_NONE) {
529
4.06k
        if(request->clientCertificate.length > 0) {
530
22
            UA_LOG_WARNING_CHANNEL(server->config.logging, channel,
531
22
                                   "CreateSession: Ignoring client certificate "
532
22
                                   "on SecurityPolicy None (Part 4, 5.6.2.2)");
533
22
        }
534
4.06k
    } else if(request->clientCertificate.length > 0) {
535
0
        rh->serviceResult =
536
0
            validateCertificate(server, &server->config.secureChannelPKI,
537
0
                                channel, NULL, "CreateSession",
538
0
                                &request->clientDescription,
539
0
                                request->clientCertificate);
540
0
        if(rh->serviceResult != UA_STATUSCODE_GOOD) {
541
0
            server->serverDiagnosticsSummary.securityRejectedSessionCount++;
542
0
            server->serverDiagnosticsSummary.rejectedSessionCount++;
543
0
            return;
544
0
        }
545
0
    }
546
547
    /* According to the spec, the (session) ClientNonce needs a length between
548
     * 32 and 128 bytes inclusive. This is the application nonce length and is
549
     * independent of the SecurityPolicy's SecureChannel nonce length (for ECC
550
     * policies that is the 64-byte ephemeral key, which is NOT the session
551
     * nonce). */
552
4.06k
    if(channel->securityPolicy->policyType != UA_SECURITYPOLICYTYPE_NONE &&
553
0
       (request->clientNonce.length < 32 || request->clientNonce.length > 128)) {
554
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
555
0
                             "CreateSession: The nonce provided by the client "
556
0
                             "has the wrong length");
557
0
        server->serverDiagnosticsSummary.securityRejectedSessionCount++;
558
0
        server->serverDiagnosticsSummary.rejectedSessionCount++;
559
0
        rh->serviceResult = UA_STATUSCODE_BADNONCEINVALID;
560
0
        return;
561
0
    }
562
563
    /* Create the Session */
564
4.06k
    UA_Session *newSession = NULL;
565
4.06k
    rh->serviceResult = UA_Session_create(server, channel, request, &newSession);
566
4.06k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
567
0
        server->serverDiagnosticsSummary.rejectedSessionCount++;
568
0
        return;
569
0
    }
570
571
    /* If the session name is empty, use the generated SessionId */
572
4.06k
    rh->serviceResult |= UA_String_copy(&request->sessionName,
573
4.06k
                                        &newSession->sessionName);
574
4.06k
    if(newSession->sessionName.length == 0)
575
3.99k
        rh->serviceResult |= UA_NodeId_print(&newSession->sessionId,
576
3.99k
                                             &newSession->sessionName);
577
578
    /* Configure the Session */
579
4.06k
    newSession->maxResponseMessageSize = request->maxResponseMessageSize;
580
4.06k
    newSession->maxRequestMessageSize = channel->config.localMaxMessageSize;
581
4.06k
    rh->serviceResult |= UA_ApplicationDescription_copy(&request->clientDescription,
582
4.06k
                                                        &newSession->clientDescription);
583
584
    /* The SecureChannel certificate must correspond to the client's
585
     * ApplicationCertificate. But for unencrypted SecureChannels we store the
586
     * certificate directly in the Session. We need it later when an encrypted
587
     * UserIdentityToken is sent over an unencrypted SecureChannel. */
588
4.06k
    if(channel->remoteCertificate.length == 0)
589
4.06k
        rh->serviceResult |= UA_ByteString_copy(&request->clientCertificate,
590
4.06k
                                                &newSession->clientCertificate);
591
592
    /* Retain the clientNonce for the v1.05.07 channel-bound
593
     * ActivateSession ClientSignature verification
594
     * (secureChannelEnhancements). */
595
4.06k
    rh->serviceResult |= UA_ByteString_copy(&request->clientNonce,
596
4.06k
                                            &newSession->clientNonce);
597
598
4.06k
#ifdef UA_ENABLE_DIAGNOSTICS
599
4.06k
    rh->serviceResult |= UA_String_copy(&request->serverUri,
600
4.06k
                                        &newSession->diagnostics.serverUri);
601
4.06k
    rh->serviceResult |= UA_String_copy(&request->endpointUrl,
602
4.06k
                                        &newSession->diagnostics.endpointUrl);
603
4.06k
#endif
604
605
4.06k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
606
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
607
0
                             "CreateSession: Could not create new session (%s)",
608
0
                             UA_StatusCode_name(rh->serviceResult));
609
0
        UA_Session_remove(server, newSession, UA_SHUTDOWNREASON_REJECT);
610
0
        return;
611
0
    }
612
613
    /* Get the SecurityPolicy for UserToken encryption and instantiate it. The
614
     * same selection is done for the local endpoints in
615
     * updateEndpointUserIdentityToken. Don't mix RSA/ECC between channel and
616
     * authentication. */
617
4.06k
    UA_SecurityPolicy *sessionSp = NULL;
618
4.06k
    if(request->clientCertificate.length > 0) {
619
22
        if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
620
22
            sessionSp = getDefaultEncryptedSecurityPolicy(server, sp->policyType);
621
0
        else
622
0
            sessionSp = sp;
623
22
    }
624
4.06k
    if(sessionSp) {
625
0
        rh->serviceResult =
626
0
            createCheckSessionAuthSecurityPolicyContext(server, newSession,
627
0
                                                        sessionSp, "CreateSession",
628
0
                                                        request->clientCertificate);
629
0
        if(rh->serviceResult != UA_STATUSCODE_GOOD) {
630
0
            UA_Session_remove(server, newSession, UA_SHUTDOWNREASON_REJECT);
631
0
            return;
632
0
        }
633
0
    }
634
635
    /* Generate the nonce. This uses the session-SecurityPolicy if defined.
636
     * Otherwise the SecurityPolicy of the SecureChannel. */
637
4.06k
    rh->serviceResult = UA_Session_generateNonce(newSession);
638
4.06k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
639
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
640
0
                             "CreateSession: Could not create the server nonce (%s)",
641
0
                             UA_StatusCode_name(rh->serviceResult));
642
0
        UA_Session_remove(server, newSession, UA_SHUTDOWNREASON_REJECT);
643
0
        return;
644
0
    }
645
646
    /* If an ECC policy, create an ephemeral key to be returned in the response.
647
     * The private part of the ephemeral key is persisted in the
648
     * Session-SecurityPolicy context. Until it gets overridden during
649
     * ActivateSession. */
650
4.06k
    if(sessionSp && UA_SecurityPolicy_isEcc(sessionSp) &&
651
0
       clientRequestedEphemeralKey(&request->requestHeader.additionalHeader)) {
652
0
        rh->serviceResult = addEphemeralKeyAdditionalHeader(server, newSession,
653
0
                                                            &rh->additionalHeader);
654
0
        if(rh->serviceResult != UA_STATUSCODE_GOOD) {
655
0
            UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
656
0
                                 "CreateSession: Could not prepare the ephemeral key (%s)",
657
0
                                 UA_StatusCode_name(rh->serviceResult));
658
0
            UA_Session_remove(server, newSession, UA_SHUTDOWNREASON_REJECT);
659
0
            return;
660
0
        }
661
0
    }
662
663
    /* Prepare the response */
664
4.06k
    response->sessionId = newSession->sessionId;
665
4.06k
    response->revisedSessionTimeout = (UA_Double)newSession->timeout;
666
4.06k
    response->authenticationToken = newSession->authenticationToken;
667
4.06k
    rh->serviceResult |= UA_ByteString_copy(&newSession->serverNonce,
668
4.06k
                                            &response->serverNonce);
669
    /* The CreateSessionResponse carries the Server's application instance
670
     * certificate so the Client can encrypt the UserIdentityToken with it. This
671
     * is needed even on a #None SecureChannel when the user token is encrypted
672
     * "on top" (sessionSp is then the user-token encryption policy, whose
673
     * localCertificate is the Server certificate; the #None channel policy has
674
     * no certificate). So copy it whenever a session-auth SecurityPolicy was
675
     * instantiated, regardless of the channel SecurityMode. */
676
4.06k
    if(sessionSp)
677
0
        rh->serviceResult |= UA_ByteString_copy(&sessionSp->localCertificate,
678
0
                                                &response->serverCertificate);
679
680
    /* Copy the server's endpointdescriptions into the response */
681
4.06k
    rh->serviceResult |= setCurrentEndpointsArray(server, request->endpointUrl,
682
4.06k
                                                  NULL, 0,
683
4.06k
                                                  &response->serverEndpoints,
684
4.06k
                                                  &response->serverEndpointsSize);
685
686
4.06k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
687
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
688
0
                             "CreateSession: Could not prepare the response (%s)",
689
0
                             UA_StatusCode_name(rh->serviceResult));
690
0
        UA_Session_remove(server, newSession, UA_SHUTDOWNREASON_REJECT);
691
0
        return;
692
0
    }
693
694
    /* Sign the signature */
695
4.06k
    rh->serviceResult |=
696
4.06k
        signCreateSessionResponse(server, channel, request, response);
697
4.06k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
698
0
        UA_Session_remove(server, newSession, UA_SHUTDOWNREASON_REJECT);
699
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
700
0
                             "CreateSession: Could not sign the response (%s)",
701
0
                             UA_StatusCode_name(rh->serviceResult));
702
0
        return;
703
0
    }
704
705
4.06k
#ifdef UA_ENABLE_DIAGNOSTICS
706
4.06k
    UA_EventLoop *el = server->config.eventLoop;
707
4.06k
    newSession->diagnostics.clientConnectionTime = el->dateTime_now(el);
708
4.06k
    newSession->diagnostics.clientLastContactTime =
709
4.06k
        newSession->diagnostics.clientConnectionTime;
710
711
    /* Create the object in the information model */
712
4.06k
    createSessionObject(server, newSession);
713
4.06k
#endif
714
715
4.06k
    UA_LOG_INFO_SESSION(server->config.logging, newSession, "Session created");
716
4.06k
}
717
718
static UA_StatusCode
719
checkCertificateSignature(const UA_Server *server, const UA_SecurityPolicy *tokenSp,
720
                          void *channelContext, const UA_ByteString *serverNonce,
721
                          const UA_SignatureData *signature,
722
0
                          const bool isUserTokenSignature, bool allowEmptyLocalCert) {
723
0
    UA_assert(tokenSp != NULL);
724
725
    /* Check for zero signature length */
726
0
    if(signature->signature.length == 0) {
727
0
        if(isUserTokenSignature)
728
0
            return UA_STATUSCODE_BADUSERSIGNATUREINVALID;
729
0
        return UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
730
0
    }
731
732
    /* Data to verify is calculated by appending the serverNonce to the local
733
     * certificate */
734
0
    const UA_ByteString *localCertificate = &tokenSp->localCertificate;
735
0
    UA_ByteString dataToVerify;
736
0
    size_t dataToVerifySize = localCertificate->length + serverNonce->length;
737
0
    UA_StatusCode res = UA_ByteString_allocBuffer(&dataToVerify, dataToVerifySize);
738
0
    if(res != UA_STATUSCODE_GOOD)
739
0
        return res;
740
741
0
    memcpy(dataToVerify.data, localCertificate->data, localCertificate->length);
742
0
    memcpy(dataToVerify.data + localCertificate->length, serverNonce->data, serverNonce->length);
743
744
0
 check_certificate:
745
0
    res = tokenSp->asymSignatureAlgorithm.
746
0
        verify(tokenSp, channelContext, &dataToVerify, &signature->signature);
747
0
    if(res != UA_STATUSCODE_GOOD) {
748
0
        if(isUserTokenSignature)
749
0
            res = UA_STATUSCODE_BADUSERSIGNATUREINVALID;
750
0
        else
751
0
            res = UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
752
0
    }
753
754
0
    if(dataToVerify.data != serverNonce->data)
755
0
        UA_ByteString_clear(&dataToVerify);
756
757
    /* Workaround: If the SecureChannel is #None, the client might have used the
758
     * ApplicationInstanceCertificate of the server (maybe it was in the
759
     * EndpointDescription) or not. If the MessageSecurityMode is #None, then
760
     * retry with an empty server certificate. */
761
0
    if(res != UA_STATUSCODE_GOOD && localCertificate->length > 0 && allowEmptyLocalCert) {
762
0
        localCertificate = &UA_BYTESTRING_NULL;
763
0
        dataToVerify = *serverNonce;
764
0
        goto check_certificate;
765
0
    }
766
767
0
    return res;
768
0
}
769
770
/* Always sets tokenSp (default: SecurityPolicy of the channel) */
771
static const UA_UserTokenPolicy *
772
selectTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
773
                  UA_Session *session, const UA_ExtensionObject *identityToken,
774
                  const UA_EndpointDescription *ed,
775
1.14k
                  UA_SecurityPolicy **tokenSp) {
776
    /* If no UserTokenPolicies are configured in the endpoint, then use
777
     * those configured in the AccessControl plugin. */
778
1.14k
    size_t identPoliciesSize = ed->userIdentityTokensSize;
779
1.14k
    const UA_UserTokenPolicy *identPolicies = ed->userIdentityTokens;
780
1.14k
    if(identPoliciesSize == 0) {
781
1.14k
        identPoliciesSize = server->config.accessControl.userTokenPoliciesSize;
782
1.14k
        identPolicies = server->config.accessControl.userTokenPolicies;
783
1.14k
    }
784
785
    /* Match the UserTokenType */
786
1.14k
    const UA_DataType *tokenDataType = identityToken->content.decoded.type;
787
1.15k
    for(size_t j = 0; j < identPoliciesSize; j++) {
788
1.14k
        const UA_UserTokenPolicy *pol = &identPolicies[j];
789
790
        /* Part 4, Section 5.6.3.2, Table 17: A NULL or empty
791
         * UserIdentityToken should be treated as Anonymous */
792
1.14k
        if(identityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY &&
793
1.13k
           pol->tokenType == UA_USERTOKENTYPE_ANONYMOUS) {
794
1.13k
            *tokenSp = channel->securityPolicy;
795
1.13k
            return pol;
796
1.13k
        }
797
798
        /* Expect decoded content if not anonymous */
799
10
        if(!tokenDataType)
800
8
            continue;
801
802
        /* Match the DataType of the provided token with the policy */
803
2
        switch(pol->tokenType) {
804
1
        case UA_USERTOKENTYPE_ANONYMOUS:
805
1
            if(tokenDataType != &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN])
806
1
                continue;
807
0
            break;
808
0
        case UA_USERTOKENTYPE_USERNAME:
809
0
            if(tokenDataType != &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN])
810
0
                continue;
811
0
            break;
812
1
        case UA_USERTOKENTYPE_CERTIFICATE:
813
1
            if(tokenDataType != &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN])
814
1
                continue;
815
0
            break;
816
0
        case UA_USERTOKENTYPE_ISSUEDTOKEN:
817
0
            if(tokenDataType != &UA_TYPES[UA_TYPES_ISSUEDIDENTITYTOKEN])
818
0
                continue;
819
0
            break;
820
0
        default:
821
0
            continue;
822
2
        }
823
824
        /* All valid token data types start with a string policyId. Casting
825
         * to anonymous hence works for all of them. */
826
0
        UA_AnonymousIdentityToken *token = (UA_AnonymousIdentityToken*)
827
0
            identityToken->content.decoded.data;
828
829
        /* In setCurrentEndpointsArray we prepend the PolicyId with the
830
         * SecurityMode of the endpoint and the postfix of the
831
         * SecurityPolicyUri to make it unique. Check the PolicyId. */
832
0
        if(pol->policyId.length > token->policyId.length)
833
0
            continue;
834
0
        UA_String policyPrefix = token->policyId;
835
0
        policyPrefix.length = pol->policyId.length;
836
0
        if(!UA_String_equal(&policyPrefix, &pol->policyId))
837
0
            continue;
838
839
        /* Get the SecurityPolicy for the endpoint from the postfix */
840
0
        UA_String utPolPostfix = securityPolicyUriPostfix(token->policyId);
841
0
        UA_SecurityPolicy *candidateSp =
842
0
            getSecurityPolicyByPostfix(server, utPolPostfix);
843
0
        if(!candidateSp) {
844
0
            UA_LOG_WARNING_SESSION(server->config.logging, session,
845
0
                                   "ActivateSession: The UserTokenPolicy of "
846
0
                                   "the endpoint defines an unknown "
847
0
                                   "SecurityPolicy %S",
848
0
                                   pol->securityPolicyUri);
849
0
            continue;
850
0
        }
851
852
        /* A non-anonymous authentication token is transmitted over an
853
         * unencrypted SecureChannel */
854
0
        if(pol->tokenType != UA_USERTOKENTYPE_ANONYMOUS &&
855
0
           channel->securityPolicy->policyType == UA_SECURITYPOLICYTYPE_NONE &&
856
0
           candidateSp->policyType == UA_SECURITYPOLICYTYPE_NONE) {
857
            /* Check if the allowNonePolicyPassword option is set.
858
             * But this exception only works for Username/Password. */
859
0
            if(!server->config.allowNonePolicyPassword ||
860
0
               pol->tokenType != UA_USERTOKENTYPE_USERNAME)
861
0
                continue;
862
0
        }
863
864
        /* Found a match policy */
865
0
        *tokenSp = candidateSp;
866
0
        return pol;
867
0
    }
868
869
5
    return NULL;
870
1.14k
}
871
872
static void
873
selectEndpointAndTokenPolicy(UA_Server *server, UA_SecureChannel *channel,
874
                             UA_Session *session,
875
                             const UA_ExtensionObject *identityToken,
876
                             const UA_EndpointDescription **ed,
877
                             const UA_UserTokenPolicy **utp,
878
1.14k
                             UA_SecurityPolicy **tokenSp) {
879
1.14k
    UA_ServerConfig *sc = &server->config;
880
1.14k
    for(size_t i = 0; i < sc->endpointsSize; ++i) {
881
1.14k
        const UA_EndpointDescription *desc = &sc->endpoints[i];
882
883
        /* Match the Security Mode */
884
1.14k
        if(desc->securityMode != channel->securityMode)
885
0
            continue;
886
887
        /* Match the SecurityPolicy of the endpoint with the current channel */
888
1.14k
        if(!UA_String_equal(&desc->securityPolicyUri,
889
1.14k
                            &channel->securityPolicy->policyUri))
890
0
            continue;
891
892
        /* Select the UserTokenPolicy from the Endpoint */
893
1.14k
        *utp = selectTokenPolicy(server, channel, session,
894
1.14k
                                 identityToken, desc, tokenSp);
895
1.14k
        if(*utp) {
896
            /* Match found */
897
1.13k
            *ed = desc;
898
1.13k
            return;
899
1.13k
        }
900
1.14k
    }
901
1.14k
}
902
903
static UA_StatusCode
904
0
hideX509IdentityTokenValidationStatus(UA_StatusCode status) {
905
0
    if(status == UA_STATUSCODE_GOOD)
906
0
        return UA_STATUSCODE_GOOD;
907
0
    return UA_STATUSCODE_BADIDENTITYTOKENREJECTED;
908
0
}
909
910
static UA_StatusCode
911
checkActivateSessionX509(UA_Server *server, UA_SecureChannel *channel, UA_Session *session,
912
                         const UA_SecurityPolicy *tokenSp, UA_X509IdentityToken* token,
913
0
                         const UA_SignatureData *tokenSignature) {
914
    /* The SecurityPolicy must not be None for the signature */
915
0
    if(tokenSp->policyType == UA_SECURITYPOLICYTYPE_NONE)
916
0
        return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
917
918
    /* We need a channel context with the user certificate in order to reuse
919
     * the signature checking code. */
920
0
    void *tempChannelContext;
921
0
    UA_StatusCode res = tokenSp->newChannelContext(tokenSp, &token->certificateData,
922
0
                                                   &tempChannelContext);
923
0
    if(res != UA_STATUSCODE_GOOD) {
924
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
925
0
                             "ActivateSession: Failed to create a context "
926
0
                             "for the SecurityPolicy %S", tokenSp->policyUri);
927
0
        return res;
928
0
    }
929
930
    /* Check the user token signature. The channel-bound v1.05.07 layout (see
931
     * the cert-role table at UA_SecureChannel_buildUserTokenSignatureData) is
932
     * used only when BOTH the SecureChannel AND the user-token SecurityPolicy
933
     * are enhanced; a legacy RSA / old-ECC user token uses the legacy layout
934
     * even over an enhanced (AesGcm) SecureChannel. */
935
0
    if(UA_SecurityPolicy_isEnhancedSecurity(channel->securityPolicy) &&
936
0
       UA_SecurityPolicy_isEnhancedSecurity(tokenSp)) {
937
0
        if(tokenSignature->signature.length == 0) {
938
0
            res = UA_STATUSCODE_BADUSERSIGNATUREINVALID;
939
0
            goto out;
940
0
        }
941
0
        UA_ByteString dataToVerify = UA_BYTESTRING_NULL;
942
0
        res = UA_SecureChannel_buildUserTokenSignatureData(
943
0
            channel, &session->serverNonce, &session->clientNonce,
944
0
            &channel->securityPolicy->localCertificate,
945
0
            &channel->securityPolicy->localCertificate,
946
0
            &channel->remoteCertificate, &channel->remoteCertificate, &dataToVerify);
947
0
        if(res == UA_STATUSCODE_GOOD) {
948
0
            res = tokenSp->asymSignatureAlgorithm.verify(
949
0
                tokenSp, tempChannelContext, &dataToVerify, &tokenSignature->signature);
950
0
            if(res != UA_STATUSCODE_GOOD)
951
0
                res = UA_STATUSCODE_BADUSERSIGNATUREINVALID;
952
0
        }
953
0
        UA_ByteString_clear(&dataToVerify);
954
0
    } else {
955
0
        res = checkCertificateSignature(server, tokenSp, tempChannelContext, &session->serverNonce,
956
0
                                        tokenSignature, true,
957
0
                                        (channel->securityMode == UA_MESSAGESECURITYMODE_NONE));
958
0
    }
959
0
    if(res != UA_STATUSCODE_GOOD) {
960
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
961
0
                             "ActivateSession: User token signature check "
962
0
                             "failed with StatusCode %s", UA_StatusCode_name(res));
963
0
        goto out;
964
0
    }
965
966
    /* Validate the certificate against the SessionPKI */
967
0
    res = validateCertificate(server, &server->config.sessionPKI,
968
0
                              session->channel, session, "ActivateSession",
969
0
                              NULL, token->certificateData);
970
0
    res = hideX509IdentityTokenValidationStatus(res);
971
972
0
 out:
973
    /* Delete the temporary channel context */
974
0
    tokenSp->deleteChannelContext(tokenSp, tempChannelContext);
975
0
    return res;
976
0
}
977
978
static UA_StatusCode
979
decryptUserToken(UA_Server *server, UA_Session *session, UA_SecureChannel *channel,
980
                 UA_SecurityPolicy *tokenSp, UA_ByteString *token,
981
0
                 const UA_String encryptionAlgorithm) {
982
    /* Not encrypted */
983
0
    if(tokenSp->policyType == UA_SECURITYPOLICYTYPE_NONE) {
984
0
        if(channel->securityMode == UA_MESSAGESECURITYMODE_NONE)
985
0
            UA_LOG_WARNING_SESSION(server->config.logging, session,
986
0
                                   "ActivateSession: Processing an unencrypted "
987
0
                                   "UserToken. This is dangerous for the server "
988
0
                                   "to allow.");
989
0
        return UA_STATUSCODE_GOOD;
990
0
    }
991
992
    /* Test if the correct encryption algorithm is used. Note that some clients
993
     * don't set the EncryptionAlgorithmUri. Skip the check for those.*/
994
0
    if(encryptionAlgorithm.length > 0 &&
995
0
       !UA_String_equal(&tokenSp->asymEncryptionAlgorithm.uri,
996
0
                        &encryptionAlgorithm)) {
997
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
998
0
                             "ActivateSession: Encryption algorithm used "
999
0
                             "for the UserIdentityToken does not match "
1000
0
                             "the endpoint");
1001
0
        return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
1002
0
    }
1003
1004
    /* Try to create an instance of the authentication SecurityPolicy to decrypt
1005
     * the UserIdentityToken. For RSA-based async encryption we don't need that. */
1006
0
    UA_ByteString applicationCert = (channel->remoteCertificate.length > 0) ?
1007
0
        channel->remoteCertificate : session->clientCertificate;
1008
0
    UA_StatusCode res =
1009
0
        createCheckSessionAuthSecurityPolicyContext(server, session, tokenSp,
1010
0
                                                    "ActivateSession", applicationCert);
1011
0
    if(res != UA_STATUSCODE_GOOD)
1012
0
        return res;
1013
1014
    /* Decrypt the token. Differentiate between secret encryptions (ECC,
1015
     * legacy).
1016
     * TODO: Implement "modern" RSA secret encryption */
1017
0
    if(UA_SecurityPolicy_isEcc(tokenSp)) {
1018
0
        res = decryptUserTokenEcc(server->config.logging, channel,
1019
0
                                session->sessionSp, session->sessionSpContext,
1020
0
                                session->serverNonce, token);
1021
0
    } else {
1022
0
        res = decryptSecretLegacy(session->sessionSp, session->sessionSpContext,
1023
0
                                  session->serverNonce, token);
1024
0
    }
1025
0
    if(res != UA_STATUSCODE_GOOD) {
1026
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
1027
0
                             "ActivateSession: Could not decrypt/"
1028
0
                             "cryptographically validate the UserIdentityToken "
1029
0
                             "with the StatusCode %s", UA_StatusCode_name(res));
1030
0
    }
1031
0
    return res;
1032
0
}
1033
1034
/* TODO: Check all of the following: The Server shall verify that the
1035
 * Certificate the Client used to create the new SecureChannel is the same as
1036
 * the Certificate used to create the original SecureChannel. In addition, the
1037
 * Server shall verify that the Client supplied a UserIdentityToken that is
1038
 * identical to the token currently associated with the Session. Once the Server
1039
 * accepts the new SecureChannel it shall reject requests sent via the old
1040
 * SecureChannel. */
1041
1042
#define UA_SESSION_REJECT                                               \
1043
119
    do {                                                                \
1044
119
        server->serverDiagnosticsSummary.rejectedSessionCount++;        \
1045
119
        return;                                                         \
1046
119
    } while(0)
1047
1048
#define UA_SECURITY_REJECT                                              \
1049
0
    do {                                                                \
1050
0
        server->serverDiagnosticsSummary.securityRejectedSessionCount++; \
1051
0
        server->serverDiagnosticsSummary.rejectedSessionCount++;        \
1052
0
        return;                                                         \
1053
0
    } while(0)
1054
1055
void
1056
Service_ActivateSession(UA_Server *server, UA_SecureChannel *channel,
1057
                        const UA_ActivateSessionRequest *req,
1058
1.25k
                        UA_ActivateSessionResponse *resp) {
1059
1.25k
    UA_LOCK_ASSERT(&server->serviceMutex);
1060
1.25k
    UA_ResponseHeader *rh = &resp->responseHeader;
1061
1062
    /* Get the session */
1063
1.25k
    UA_Session *session =
1064
1.25k
        getSessionByToken(server, &req->requestHeader.authenticationToken);
1065
1.25k
    if(!session) {
1066
114
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
1067
114
                             "ActivateSession: Session not found");
1068
114
        rh->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
1069
114
        UA_SESSION_REJECT;
1070
114
    }
1071
1072
    /* Part 4, §5.6.3: When the ActivateSession Service is called for the
1073
     * first time then the Server shall reject the request if the
1074
     * SecureChannel is not same as the one associated with the
1075
     * CreateSession request. Subsequent calls to ActivateSession may be
1076
     * associated with different SecureChannels. */
1077
1.14k
    if(!session->activated && session->channel != channel) {
1078
0
        UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
1079
0
                             "ActivateSession: The Session has to be initially "
1080
0
                             "activated on the SecureChannel that created it");
1081
0
        rh->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
1082
0
        UA_SESSION_REJECT;
1083
0
    }
1084
1085
    /* Has the session timed out? */
1086
1.14k
    UA_EventLoop *el = server->config.eventLoop;
1087
1.14k
    UA_DateTime nowMonotonic = el->dateTime_nowMonotonic(el);
1088
1.14k
    if(session->validTill < nowMonotonic) {
1089
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
1090
0
                             "ActivateSession: The Session has timed out");
1091
0
        rh->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
1092
0
        UA_SESSION_REJECT;
1093
0
    }
1094
1095
    /* Check the client signature */
1096
1.14k
    if(channel->securityMode == UA_MESSAGESECURITYMODE_SIGN ||
1097
1.14k
       channel->securityMode == UA_MESSAGESECURITYMODE_SIGNANDENCRYPT) {
1098
0
        const UA_SecurityPolicy *csp = channel->securityPolicy;
1099
0
        if(UA_SecurityPolicy_isEnhancedSecurity(csp)) {
1100
            /* Channel-bound v1.05.07 ClientSignature (see the cert-role table at
1101
             * UA_SecureChannel_buildActivateSessionSignatureData). clientNonce is
1102
             * the ClientNonce stored at CreateSession. */
1103
0
            if(req->clientSignature.signature.length == 0) {
1104
0
                rh->serviceResult = UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
1105
0
            } else {
1106
0
                UA_ByteString dataToVerify = UA_BYTESTRING_NULL;
1107
0
                rh->serviceResult = UA_SecureChannel_buildActivateSessionSignatureData(
1108
0
                    channel, &session->serverNonce, &session->clientNonce,
1109
0
                    &csp->localCertificate, &csp->localCertificate,
1110
0
                    &channel->remoteCertificate, &dataToVerify);
1111
0
                if(rh->serviceResult == UA_STATUSCODE_GOOD) {
1112
0
                    rh->serviceResult = csp->asymSignatureAlgorithm.verify(
1113
0
                        csp, channel->channelContext, &dataToVerify,
1114
0
                        &req->clientSignature.signature);
1115
0
                    if(rh->serviceResult != UA_STATUSCODE_GOOD)
1116
0
                        rh->serviceResult = UA_STATUSCODE_BADAPPLICATIONSIGNATUREINVALID;
1117
0
                }
1118
0
                UA_ByteString_clear(&dataToVerify);
1119
0
            }
1120
0
        } else {
1121
0
            rh->serviceResult =
1122
0
                checkCertificateSignature(server, channel->securityPolicy,
1123
0
                                          channel->channelContext, &session->serverNonce,
1124
0
                                          &req->clientSignature, false, false);
1125
0
        }
1126
0
        if(rh->serviceResult != UA_STATUSCODE_GOOD) {
1127
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
1128
0
                                 "ActivateSession: Client signature check failed "
1129
0
                                 "with StatusCode %s",
1130
0
                                 UA_StatusCode_name(rh->serviceResult));
1131
0
            UA_SECURITY_REJECT;
1132
0
        }
1133
0
    }
1134
1135
    /* Find the matching Endpoint with UserTokenPolicy.
1136
     * Also sets the SecurityPolicy used to encrypt the token. */
1137
1.14k
    const UA_EndpointDescription *ed = NULL;
1138
1.14k
    const UA_UserTokenPolicy *utp = NULL;
1139
1.14k
    UA_SecurityPolicy *tokenSp = NULL;
1140
1.14k
    selectEndpointAndTokenPolicy(server, channel, session,
1141
1.14k
                                 &req->userIdentityToken,
1142
1.14k
                                 &ed, &utp, &tokenSp);
1143
1.14k
    if(!ed || !tokenSp) {
1144
5
        UA_LOG_ERROR_SESSION(server->config.logging, session,
1145
5
                             "ActivateSession: Requested Endpoint/UserTokenPolicy "
1146
5
                             "not available");
1147
5
        rh->serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
1148
5
        UA_SESSION_REJECT;
1149
5
    }
1150
1151
    /* Decrypt (or validate the signature) of the UserToken. The DataType of the
1152
     * UserToken was already checked in selectEndpointAndTokenPolicy. This
1153
     * replaces the content of the token in-situ. */
1154
1.13k
    switch(utp->tokenType) {
1155
1.13k
    case UA_USERTOKENTYPE_ANONYMOUS:
1156
1.13k
        break;
1157
0
    case UA_USERTOKENTYPE_USERNAME: {
1158
0
        UA_UserNameIdentityToken *token = (UA_UserNameIdentityToken *)
1159
0
           req->userIdentityToken.content.decoded.data;
1160
0
        rh->serviceResult =
1161
0
            decryptUserToken(server, session, channel, tokenSp,
1162
0
                             &token->password, token->encryptionAlgorithm);
1163
0
        break; }
1164
0
    case UA_USERTOKENTYPE_CERTIFICATE: {
1165
        /* Check the signature and verify the certificate in the sessionPKI */
1166
0
        UA_X509IdentityToken* x509token = (UA_X509IdentityToken*)
1167
0
            req->userIdentityToken.content.decoded.data;
1168
0
        rh->serviceResult =
1169
0
            checkActivateSessionX509(server, channel, session, tokenSp, x509token,
1170
0
                                     &req->userTokenSignature);
1171
0
        break; }
1172
0
    case UA_USERTOKENTYPE_ISSUEDTOKEN: {
1173
0
        UA_IssuedIdentityToken *token = (UA_IssuedIdentityToken*)
1174
0
            req->userIdentityToken.content.decoded.data;
1175
0
        rh->serviceResult =
1176
0
            decryptUserToken(server, session, channel, tokenSp,
1177
0
                             &token->tokenData, token->encryptionAlgorithm);
1178
0
        break; }
1179
0
    default:
1180
0
        rh->serviceResult = UA_STATUSCODE_BADIDENTITYTOKENINVALID;
1181
0
        break;
1182
1.13k
    }
1183
1184
    /* Could not decrypt the UserIdentityToken */
1185
1.13k
    if(rh->serviceResult != UA_STATUSCODE_GOOD)
1186
0
        UA_SECURITY_REJECT;
1187
1188
    /* Callback into the access control plugin.
1189
     * This will attach a custom context pointer to the session. */
1190
1.13k
    rh->serviceResult = server->config.accessControl.
1191
1.13k
        activateSession(server, &server->config.accessControl, ed,
1192
1.13k
                        &channel->remoteCertificate, &session->sessionId,
1193
1.13k
                        &req->userIdentityToken, &session->context);
1194
1.13k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
1195
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
1196
0
                             "ActivateSession: The AccessControl plugin "
1197
0
                             "denied the activation with the StatusCode %s",
1198
0
                             UA_StatusCode_name(rh->serviceResult));
1199
0
        UA_SECURITY_REJECT;
1200
0
    }
1201
1202
    /* Attach the session to the currently used channel if the session isn't
1203
     * attached to a channel or if the session is activated on a different
1204
     * channel than it is attached to. */
1205
1.13k
    if(!session->channel || session->channel != channel) {
1206
        /* Attach the new SecureChannel, the old channel will be detached if present */
1207
0
        UA_Session_attachToSecureChannel(server, session, channel);
1208
0
        UA_LOG_INFO_SESSION(server->config.logging, session,
1209
0
                            "ActivateSession: Session attached to new channel");
1210
0
    }
1211
1212
    /* Generate a new session nonce for the next time ActivateSession is called */
1213
1.13k
    rh->serviceResult = UA_Session_generateNonce(session);
1214
1.13k
    rh->serviceResult |= UA_ByteString_copy(&session->serverNonce,
1215
1.13k
                                            &resp->serverNonce);
1216
1.13k
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
1217
0
        UA_Session_detachFromSecureChannel(server, session);
1218
0
        UA_LOG_ERROR_SESSION(server->config.logging, session,
1219
0
                             "ActivateSession: Could not generate the server nonce");
1220
0
        UA_SESSION_REJECT;
1221
0
    }
1222
1223
    /* Set the Locale */
1224
1.13k
    if(req->localeIdsSize > 0) {
1225
        /* Part 4, §5.6.3.2: This parameter only needs to be specified during
1226
         * the first call to ActivateSession during a single application
1227
         * Session. If it is not specified the Server shall keep using the
1228
         * current localeIds for the Session. */
1229
148
        UA_String *tmpLocaleIds;
1230
148
        rh->serviceResult |=
1231
148
            UA_Array_copy(req->localeIds, req->localeIdsSize,
1232
148
                          (void**)&tmpLocaleIds, &UA_TYPES[UA_TYPES_STRING]);
1233
148
        if(rh->serviceResult != UA_STATUSCODE_GOOD) {
1234
0
            UA_Session_detachFromSecureChannel(server, session);
1235
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
1236
0
                                 "ActivateSession: Could not store the "
1237
0
                                 "Session LocaleIds");
1238
0
            UA_SESSION_REJECT;
1239
0
        }
1240
148
        UA_Array_delete(session->localeIds, session->localeIdsSize,
1241
148
                        &UA_TYPES[UA_TYPES_STRING]);
1242
148
        session->localeIds = tmpLocaleIds;
1243
148
        session->localeIdsSize = req->localeIdsSize;
1244
148
    }
1245
1246
    /* Update the Session lifetime */
1247
1.13k
    UA_DateTime now = el->dateTime_now(el);
1248
1.13k
    nowMonotonic = el->dateTime_nowMonotonic(el);
1249
1.13k
    UA_Session_updateLifetime(session, now, nowMonotonic);
1250
1251
    /* If ECC policy, create the new ephemeral key to be returned in the
1252
     * ActivateSession response */
1253
1.13k
    const UA_SecurityPolicy *sessionSp = session->sessionSp;
1254
1.13k
    if(sessionSp && session->sessionSpContext &&
1255
0
       UA_SecurityPolicy_isEcc(sessionSp) &&
1256
0
       clientRequestedEphemeralKey(&req->requestHeader.additionalHeader)) {
1257
0
        rh->serviceResult = addEphemeralKeyAdditionalHeader(server, session,
1258
0
                                                            &rh->additionalHeader);
1259
0
        if(rh->serviceResult != UA_STATUSCODE_GOOD) {
1260
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
1261
0
                                 "ActivateSession: Could not prepare the "
1262
0
                                 "ephemeral key (%s)",
1263
0
                                 UA_StatusCode_name(rh->serviceResult));
1264
0
            UA_SECURITY_REJECT;
1265
0
        }
1266
0
    }
1267
1268
    /* Activate the session */
1269
1.13k
    if(!session->activated) {
1270
791
        session->activated = true;
1271
791
        server->activeSessionCount++;
1272
791
        server->serverDiagnosticsSummary.cumulatedSessionCount++;
1273
791
    }
1274
1275
    /* Store the ClientUserId. tokenType can be NULL for the anonymous user. */
1276
1.13k
    UA_String_clear(&session->clientUserIdOfSession);
1277
1.13k
    const UA_DataType *tokenType = req->userIdentityToken.content.decoded.type;
1278
1.13k
    if(tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
1279
0
        const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*)
1280
0
            req->userIdentityToken.content.decoded.data;
1281
0
        UA_String_copy(&userToken->userName, &session->clientUserIdOfSession);
1282
1.13k
    } else if(tokenType == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
1283
0
        UA_X509IdentityToken* userCertToken = (UA_X509IdentityToken*)
1284
0
            req->userIdentityToken.content.decoded.data;
1285
0
        UA_CertificateUtils_getSubjectName(&session->clientUserIdOfSession,
1286
0
                                           &userCertToken->certificateData);
1287
1.13k
    } else {
1288
        /* TODO: Handle issued token */
1289
1.13k
    }
1290
1291
1.13k
#ifdef UA_ENABLE_DIAGNOSTICS
1292
    /* Add the ClientUserId to the diagnostics history. Ignoring errors in _appendCopy. */
1293
1.13k
    UA_SessionSecurityDiagnosticsDataType *ssd = &session->securityDiagnostics;
1294
1.13k
    UA_Array_appendCopy((void**)&ssd->clientUserIdHistory,
1295
1.13k
                        &ssd->clientUserIdHistorySize,
1296
1.13k
                        &ssd->clientUserIdOfSession,
1297
1.13k
                        &UA_TYPES[UA_TYPES_STRING]);
1298
1299
    /* Store the auth mechanism */
1300
1.13k
    UA_String_clear(&ssd->authenticationMechanism);
1301
1.13k
    switch(utp->tokenType) {
1302
1.13k
    case UA_USERTOKENTYPE_ANONYMOUS:
1303
1.13k
        ssd->authenticationMechanism = UA_STRING_ALLOC("Anonymous"); break;
1304
0
    case UA_USERTOKENTYPE_USERNAME:
1305
0
        ssd->authenticationMechanism = UA_STRING_ALLOC("UserName"); break;
1306
0
    case UA_USERTOKENTYPE_CERTIFICATE:
1307
0
        ssd->authenticationMechanism = UA_STRING_ALLOC("Certificate"); break;
1308
0
    case UA_USERTOKENTYPE_ISSUEDTOKEN:
1309
0
        ssd->authenticationMechanism = UA_STRING_ALLOC("IssuedToken"); break;
1310
0
    default: break;
1311
1.13k
    }
1312
1.13k
#endif
1313
1314
    /* Notify the application */
1315
1.13k
    notifySession(server, session, UA_APPLICATIONNOTIFICATIONTYPE_SESSION_ACTIVATED);
1316
1317
    /* Log the user for which the Session was activated */
1318
1.13k
    UA_LOG_INFO_SESSION(server->config.logging, session,
1319
1.13k
                        "ActivateSession: Session activated with ClientUserId \"%S\"",
1320
1.13k
                        session->clientUserIdOfSession);
1321
1.13k
}
1322
1323
void
1324
Service_CloseSession(UA_Server *server, UA_SecureChannel *channel,
1325
                     const UA_CloseSessionRequest *request,
1326
107
                     UA_CloseSessionResponse *response) {
1327
107
    UA_LOCK_ASSERT(&server->serviceMutex);
1328
107
    UA_ResponseHeader *rh = &response->responseHeader;
1329
1330
    /* Part 4, 5.6.4: When the CloseSession Service is called before the Session
1331
     * is successfully activated, the Server shall reject the request if the
1332
     * SecureChannel is not the same as the one associated with the
1333
     * CreateSession request.
1334
     *
1335
     * A non-activated Session is already bound to the SecureChannel that
1336
     * created the Session. */
1337
107
    UA_Session *session = NULL;
1338
107
    const UA_NodeId *authToken = &request->requestHeader.authenticationToken;
1339
107
    rh->serviceResult = getBoundSession(server, channel, authToken, &session);
1340
107
    if(!session && rh->serviceResult == UA_STATUSCODE_GOOD)
1341
0
        rh->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
1342
107
    if(rh->serviceResult != UA_STATUSCODE_GOOD) {
1343
2
        UA_LOG_WARNING_CHANNEL(server->config.logging, channel,
1344
2
                               "CloseSession: No Session activated to the SecureChannel");
1345
2
        return;
1346
2
    }
1347
1348
105
    UA_assert(session); /* Assured by the previous section */
1349
105
    UA_LOG_INFO_SESSION(server->config.logging, session, "Closing the Session");
1350
1351
105
#ifdef UA_ENABLE_SUBSCRIPTIONS
1352
    /* If Subscriptions are not deleted, detach them from the Session */
1353
105
    if(!request->deleteSubscriptions) {
1354
95
        UA_Subscription *sub, *sub_tmp;
1355
95
        TAILQ_FOREACH_SAFE(sub, &session->subscriptions, sessionListEntry, sub_tmp) {
1356
0
            UA_LOG_INFO_SUBSCRIPTION(server->config.logging, sub,
1357
0
                                     "Detaching the Subscription from the Session");
1358
0
            UA_Session_detachSubscription(server, session, sub, true);
1359
0
        }
1360
95
    }
1361
105
#endif
1362
1363
    /* Remove the sesison */
1364
105
    UA_Session_remove(server, session, UA_SHUTDOWNREASON_CLOSE);
1365
105
}
1366
1367
UA_Boolean
1368
Service_Cancel(UA_Server *server, UA_Session *session,
1369
2
               const UA_CancelRequest *request, UA_CancelResponse *response) {
1370
    /* If multithreading is disabled, then there are no async services. If all
1371
     * services are answered "right away", then there are no services that can
1372
     * be cancelled. */
1373
2
    response->cancelCount = UA_AsyncManager_cancel(server, session,
1374
2
                                                   request->requestHandle);
1375
1376
    /* Publish requests for Subscriptions are stored separately */
1377
2
#ifdef UA_ENABLE_SUBSCRIPTIONS
1378
2
    UA_PublishResponseEntry *pre, *pre_tmp;
1379
2
    UA_PublishResponseEntry *prev = NULL;
1380
2
    SIMPLEQ_FOREACH_SAFE(pre, &session->responseQueue, listEntry, pre_tmp) {
1381
        /* Skip entry and set as the previous entry that is kept in the list */
1382
0
        if(pre->response.responseHeader.requestHandle != request->requestHandle) {
1383
0
            prev = pre;
1384
0
            continue;
1385
0
        }
1386
1387
        /* Dequeue */
1388
0
        if(prev)
1389
0
            SIMPLEQ_REMOVE_AFTER(&session->responseQueue, prev, listEntry);
1390
0
        else
1391
0
            SIMPLEQ_REMOVE_HEAD(&session->responseQueue, listEntry);
1392
0
        session->responseQueueSize--;
1393
1394
        /* Send response and clean up */
1395
0
        response->responseHeader.serviceResult = UA_STATUSCODE_BADREQUESTCANCELLEDBYCLIENT;
1396
0
        sendResponse(server, session->channel, pre->requestId, (UA_Response *)response,
1397
0
                     &UA_TYPES[UA_TYPES_PUBLISHRESPONSE]);
1398
0
        UA_PublishResponse_clear(&pre->response);
1399
0
        UA_free(pre);
1400
1401
        /* Increase the CancelCount */
1402
0
        response->cancelCount++;
1403
0
    }
1404
2
#endif
1405
1406
    return true;
1407
2
}