Coverage Report

Created: 2026-08-31 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541/plugins/ua_accesscontrol_default.c
Line
Count
Source
1
/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
2
 * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
3
 *
4
 *    Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
5
 *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
6
 *    Copyright 2019 (c) HMS Industrial Networks AB (Author: Jonas Green)
7
 *    Copyright 2026 (c) o6 Automation GmbH (Author: Julius Pfrommer)
8
 */
9
10
#include <open62541/plugin/accesscontrol_default.h>
11
12
#ifdef UA_ENABLE_RBAC
13
/* Internal RBAC API; not declared in public plugin headers. */
14
UA_StatusCode
15
UA_Server_getEffectivePermissions(UA_Server *server,
16
                                  const UA_NodeId *sessionId,
17
                                  const UA_NodeId *nodeId,
18
                                  UA_PermissionType *effectivePermissions);
19
#endif
20
21
/* Example access control management. Anonymous and username / password login.
22
 * The access rights are maximally permissive.
23
 *
24
 * FOR PRODUCTION USE, THIS EXAMPLE PLUGIN SHOULD BE REPLACED WITH LESS
25
 * PERMISSIVE ACCESS CONTROL.
26
 *
27
 * For TransferSubscriptions, we check whether the transfer happens between
28
 * Sessions for the same user. */
29
30
typedef struct {
31
    UA_Boolean allowAnonymous;
32
    size_t usernamePasswordLoginSize;
33
    UA_UsernamePasswordLogin *usernamePasswordLogin;
34
    UA_UsernamePasswordLoginCallback loginCallback;
35
    void *loginContext;
36
    UA_CertificateGroup verifyX509;
37
} AccessControlContext;
38
39
#define ANONYMOUS_POLICY "open62541-anonymous-policy"
40
#define CERTIFICATE_POLICY "open62541-certificate-policy"
41
#define USERNAME_POLICY "open62541-username-policy"
42
43
/************************/
44
/* Access Control Logic */
45
/************************/
46
47
static UA_StatusCode
48
activateSession_default(UA_Server *server, UA_AccessControl *ac,
49
                        const UA_EndpointDescription *endpointDescription,
50
                        const UA_ByteString *secureChannelRemoteCertificate,
51
                        const UA_NodeId *sessionId,
52
                        const UA_ExtensionObject *userIdentityToken,
53
1.22k
                        void **sessionContext) {
54
1.22k
    AccessControlContext *context = (AccessControlContext*)ac->context;
55
56
    /* The empty token is interpreted as anonymous */
57
1.22k
    UA_AnonymousIdentityToken anonToken;
58
1.22k
    UA_ExtensionObject tmpIdentity;
59
1.22k
    if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
60
1.22k
        UA_AnonymousIdentityToken_init(&anonToken);
61
1.22k
        UA_ExtensionObject_init(&tmpIdentity);
62
1.22k
        UA_ExtensionObject_setValueNoDelete(&tmpIdentity,
63
1.22k
                                            &anonToken,
64
1.22k
                                            &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]);
65
1.22k
        userIdentityToken = &tmpIdentity;
66
1.22k
    }
67
68
    /* Could the token be decoded? */
69
1.22k
    if(userIdentityToken->encoding != UA_EXTENSIONOBJECT_DECODED &&
70
1.22k
       userIdentityToken->encoding != UA_EXTENSIONOBJECT_DECODED_NODELETE)
71
0
        return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
72
73
1.22k
    const UA_DataType *tokenType = userIdentityToken->content.decoded.type;
74
1.22k
    if(tokenType == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
75
        /* Anonymous login */
76
1.22k
        if(!context->allowAnonymous)
77
0
            return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
78
1.22k
        if(context->loginCallback) {
79
0
            UA_StatusCode res =
80
0
                context->loginCallback(&UA_STRING_NULL, &UA_BYTESTRING_NULL,
81
0
                                       context->usernamePasswordLoginSize,
82
0
                                       context->usernamePasswordLogin,
83
0
                                       sessionContext, context->loginContext);
84
0
            if(res != UA_STATUSCODE_GOOD)
85
0
                return UA_STATUSCODE_BADUSERACCESSDENIED;
86
0
        }
87
1.22k
    } else if(tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
88
        /* Username and password */
89
0
        const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*)
90
0
            userIdentityToken->content.decoded.data;
91
92
        /* Empty username and password */
93
0
        if(userToken->userName.length == 0 && userToken->password.length == 0)
94
0
            return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
95
96
        /* Try to match username/pw */
97
0
        if(context->loginCallback) {
98
            /* Configured callback */
99
0
            UA_StatusCode res =
100
0
                context->loginCallback(&userToken->userName, &userToken->password,
101
0
                                       context->usernamePasswordLoginSize,
102
0
                                       context->usernamePasswordLogin,
103
0
                                       sessionContext, context->loginContext);
104
0
            if(res != UA_STATUSCODE_GOOD)
105
0
                return UA_STATUSCODE_BADUSERACCESSDENIED;
106
0
        } else {
107
            /* Compare against the configured list  */
108
0
            UA_Boolean match = false;
109
0
            for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
110
0
                UA_UsernamePasswordLogin *upl = &context->usernamePasswordLogin[i];
111
0
                if(!UA_String_equal(&userToken->userName, &upl->username))
112
0
                   continue;
113
0
                if(userToken->password.length != upl->password.length)
114
0
                    continue;
115
0
                if(!UA_constantTimeEqual(userToken->password.data,
116
0
                                         upl->password.data,
117
0
                                         upl->password.length))
118
0
                    continue;
119
0
                match = true;
120
0
                break;
121
0
            }
122
0
            if(!match)
123
0
                return UA_STATUSCODE_BADUSERACCESSDENIED;
124
0
        }
125
0
    } else if(tokenType == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
126
        /* x509 certificate was already validated against the sessionPKI in the
127
         * server */
128
0
    } else {
129
        /* Unsupported token type */
130
0
        return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
131
0
    }
132
133
    /* Store the endpoint's SecurityPolicyUri as a custom session attribute.
134
     * This is needed later in allowTransferSubscription_default to determine
135
     * whether the session was established over a secure channel. */
136
1.22k
    if(endpointDescription) {
137
1.22k
        UA_Variant spUri;
138
1.22k
        UA_Variant_setScalar(&spUri, (void*)(uintptr_t)&endpointDescription->securityPolicyUri,
139
1.22k
                             &UA_TYPES[UA_TYPES_STRING]);
140
1.22k
        UA_Server_setSessionAttribute(server, sessionId,
141
1.22k
                                      UA_QUALIFIEDNAME(0, "channelSecurityPolicyUri"),
142
1.22k
                                      &spUri);
143
1.22k
    }
144
145
1.22k
    return UA_STATUSCODE_GOOD;
146
1.22k
}
147
148
static void
149
closeSession_default(UA_Server *server, UA_AccessControl *ac,
150
9.21k
                     const UA_NodeId *sessionId, void *sessionContext) {
151
9.21k
}
152
153
/* Map RBAC PermissionType bits to the node's UserWriteMask.
154
 *
155
 * OPC UA Part 3, Table 8 defines three separate permission bits that
156
 * control attribute writing:
157
 *   - WriteAttribute  -> all WriteMask bits EXCEPT RolePermissions
158
 *                        and Historizing (the "catch-all" permission)
159
 *   - WriteRolePermissions -> UA_WRITEMASK_ROLEPERMISSIONS (bit 23)
160
 *   - WriteHistorizing     -> UA_WRITEMASK_HISTORIZING    (bit 9)
161
 *
162
 * 0xFFFFFFFF effectivePerms means "no RBAC restrictions configured" for
163
 * the node, so we return all-bits-set (fully permissive). */
164
static UA_UInt32
165
getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
166
                          const UA_NodeId *sessionId, void *sessionContext,
167
2
                          const UA_NodeId *nodeId, void *nodeContext) {
168
#ifdef UA_ENABLE_RBAC
169
    UA_PermissionType effectivePerms = 0;
170
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
171
                                                          nodeId, &effectivePerms);
172
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
173
        return 0xFFFFFFFF;
174
    UA_UInt32 userWriteMask = 0;
175
    if(effectivePerms & UA_PERMISSIONTYPE_WRITEATTRIBUTE) {
176
        /* Grant all attribute-write bits, then carve out the two that
177
         * have their own dedicated permission bits. */
178
        userWriteMask = 0xFFFFFFFF;
179
        userWriteMask &= ~UA_WRITEMASK_ROLEPERMISSIONS;
180
        userWriteMask &= ~UA_WRITEMASK_HISTORIZING;
181
    }
182
    if(effectivePerms & UA_PERMISSIONTYPE_WRITEROLEPERMISSIONS)
183
        userWriteMask |= UA_WRITEMASK_ROLEPERMISSIONS;
184
    if(effectivePerms & UA_PERMISSIONTYPE_WRITEHISTORIZING)
185
        userWriteMask |= UA_WRITEMASK_HISTORIZING;
186
    return userWriteMask;
187
#else
188
2
    return 0xFFFFFFFF;
189
2
#endif
190
2
}
191
192
/* Map RBAC PermissionType bits to the Variable node's UserAccessLevel.
193
 *
194
 * OPC UA Part 3, Table 8 maps:
195
 *   - Read          -> ACCESSLEVELMASK_READ         (bit 0)
196
 *   - Write         -> ACCESSLEVELMASK_WRITE        (bit 1)
197
 *   - ReadHistory   -> ACCESSLEVELMASK_HISTORYREAD  (bit 2)
198
 *   - InsertHistory |
199
 *     ModifyHistory |
200
 *     DeleteHistory -> ACCESSLEVELMASK_HISTORYWRITE (bit 3)
201
 *
202
 * StatusWrite (bit 5) and TimestampWrite (bit 6) are not mapped from
203
 * RBAC permissions — they remain restricted unless the node has no
204
 * RBAC configuration (0xFFFFFFFF). */
205
static UA_Byte
206
getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
207
                           const UA_NodeId *sessionId, void *sessionContext,
208
4
                           const UA_NodeId *nodeId, void *nodeContext) {
209
#ifdef UA_ENABLE_RBAC
210
    UA_PermissionType effectivePerms = 0;
211
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
212
                                                          nodeId, &effectivePerms);
213
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
214
        return 0xFF;
215
    UA_Byte userAccessLevel = 0;
216
    if(effectivePerms & UA_PERMISSIONTYPE_READ)
217
        userAccessLevel |= UA_ACCESSLEVELMASK_READ;
218
    if(effectivePerms & UA_PERMISSIONTYPE_WRITE)
219
        userAccessLevel |= UA_ACCESSLEVELMASK_WRITE;
220
    if(effectivePerms & UA_PERMISSIONTYPE_READHISTORY)
221
        userAccessLevel |= UA_ACCESSLEVELMASK_HISTORYREAD;
222
    if(effectivePerms & (UA_PERMISSIONTYPE_INSERTHISTORY |
223
                         UA_PERMISSIONTYPE_MODIFYHISTORY |
224
                         UA_PERMISSIONTYPE_DELETEHISTORY))
225
        userAccessLevel |= UA_ACCESSLEVELMASK_HISTORYWRITE;
226
    return userAccessLevel;
227
#else
228
4
    return 0xFF;
229
4
#endif
230
4
}
231
232
/* OPC UA Part 3, Table 8: Call permission -> UserExecutable attribute. */
233
static UA_Boolean
234
getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
235
                          const UA_NodeId *sessionId, void *sessionContext,
236
0
                          const UA_NodeId *methodId, void *methodContext) {
237
#ifdef UA_ENABLE_RBAC
238
    UA_PermissionType effectivePerms = 0;
239
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
240
                                                          methodId, &effectivePerms);
241
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
242
        return true;
243
    return (effectivePerms & UA_PERMISSIONTYPE_CALL) != 0;
244
#else
245
0
    return true;
246
0
#endif
247
0
}
248
249
/* Call permission is checked on both the object and the method node.
250
 * Both must grant CALL for the method invocation to be allowed. */
251
static UA_Boolean
252
getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
253
                                  const UA_NodeId *sessionId, void *sessionContext,
254
                                  const UA_NodeId *methodId, void *methodContext,
255
0
                                  const UA_NodeId *objectId, void *objectContext) {
256
#ifdef UA_ENABLE_RBAC
257
    UA_PermissionType objectPerms = 0;
258
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
259
                                                          objectId, &objectPerms);
260
    if(res != UA_STATUSCODE_GOOD)
261
        return true;
262
    if(objectPerms != 0xFFFFFFFF && !(objectPerms & UA_PERMISSIONTYPE_CALL))
263
        return false;
264
    UA_PermissionType methodPerms = 0;
265
    res = UA_Server_getEffectivePermissions(server, sessionId,
266
                                            methodId, &methodPerms);
267
    if(res != UA_STATUSCODE_GOOD)
268
        return true;
269
    if(methodPerms != 0xFFFFFFFF && !(methodPerms & UA_PERMISSIONTYPE_CALL))
270
        return false;
271
    return true;
272
#else
273
0
    return true;
274
0
#endif
275
0
}
276
277
/* AddNode permission is checked on the parent node. */
278
static UA_Boolean
279
allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
280
                     const UA_NodeId *sessionId, void *sessionContext,
281
23
                     const UA_AddNodesItem *item) {
282
#ifdef UA_ENABLE_RBAC
283
    UA_PermissionType effectivePerms = 0;
284
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
285
                                                          &item->parentNodeId.nodeId,
286
                                                          &effectivePerms);
287
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
288
        return true;
289
    return (effectivePerms & UA_PERMISSIONTYPE_ADDNODE) != 0;
290
#else
291
23
    return true;
292
23
#endif
293
23
}
294
295
/* AddReference permission is checked on the source node. */
296
static UA_Boolean
297
allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
298
                          const UA_NodeId *sessionId, void *sessionContext,
299
82
                          const UA_AddReferencesItem *item) {
300
#ifdef UA_ENABLE_RBAC
301
    UA_PermissionType effectivePerms = 0;
302
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
303
                                                          &item->sourceNodeId,
304
                                                          &effectivePerms);
305
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
306
        return true;
307
    return (effectivePerms & UA_PERMISSIONTYPE_ADDREFERENCE) != 0;
308
#else
309
82
    return true;
310
82
#endif
311
82
}
312
313
/* DeleteNode permission is checked on the node itself. */
314
static UA_Boolean
315
allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
316
                        const UA_NodeId *sessionId, void *sessionContext,
317
3.85k
                        const UA_DeleteNodesItem *item) {
318
#ifdef UA_ENABLE_RBAC
319
    UA_PermissionType effectivePerms = 0;
320
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
321
                                                          &item->nodeId,
322
                                                          &effectivePerms);
323
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
324
        return true;
325
    return (effectivePerms & UA_PERMISSIONTYPE_DELETENODE) != 0;
326
#else
327
3.85k
    return true;
328
3.85k
#endif
329
3.85k
}
330
331
/* RemoveReference permission is checked on the source node. */
332
static UA_Boolean
333
allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
334
                             const UA_NodeId *sessionId, void *sessionContext,
335
729k
                             const UA_DeleteReferencesItem *item) {
336
#ifdef UA_ENABLE_RBAC
337
    UA_PermissionType effectivePerms = 0;
338
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
339
                                                          &item->sourceNodeId,
340
                                                          &effectivePerms);
341
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
342
        return true;
343
    return (effectivePerms & UA_PERMISSIONTYPE_REMOVEREFERENCE) != 0;
344
#else
345
729k
    return true;
346
729k
#endif
347
729k
}
348
349
/* OPC UA Part 3, Table 8: Browse permission. */
350
static UA_Boolean
351
allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac,
352
                        const UA_NodeId *sessionId, void *sessionContext,
353
25
                        const UA_NodeId *nodeId, void *nodeContext) {
354
#ifdef UA_ENABLE_RBAC
355
    UA_PermissionType effectivePerms = 0;
356
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
357
                                                          nodeId, &effectivePerms);
358
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
359
        return true;
360
    return (effectivePerms & UA_PERMISSIONTYPE_BROWSE) != 0;
361
#else
362
25
    return true;
363
25
#endif
364
25
}
365
366
#ifdef UA_ENABLE_SUBSCRIPTIONS
367
static UA_Boolean
368
allowCreateSubscription_default(UA_Server *server, UA_AccessControl *ac,
369
139
                                const UA_NodeId *sessionId, void *sessionContext) {
370
139
    return true;
371
139
}
372
373
static UA_Boolean
374
allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac,
375
                                  const UA_NodeId *oldSessionId, void *oldSessionContext,
376
0
                                  const UA_NodeId *newSessionId, void *newSessionContext) {
377
0
    if(!oldSessionId)
378
0
        return false;
379
    
380
    /* Get clientUserId for both sessions */
381
0
    UA_Variant session1UserId;
382
0
    UA_Variant_init(&session1UserId);
383
0
    UA_Server_getSessionAttribute(server, oldSessionId,
384
0
                                  UA_QUALIFIEDNAME(0, "clientUserId"),
385
0
                                  &session1UserId);
386
0
    UA_Variant session2UserId;
387
0
    UA_Variant_init(&session2UserId);
388
0
    UA_Server_getSessionAttribute(server, newSessionId,
389
0
                                  UA_QUALIFIEDNAME(0, "clientUserId"),
390
0
                                  &session2UserId);
391
392
    /* clientUserId is always a String type */
393
0
    UA_Boolean result = false;
394
0
    if(session1UserId.type == &UA_TYPES[UA_TYPES_STRING] &&
395
0
       session2UserId.type == &UA_TYPES[UA_TYPES_STRING]) {
396
0
        UA_String *userId1 = (UA_String*)session1UserId.data;
397
0
        UA_String *userId2 = (UA_String*)session2UserId.data;
398
        
399
0
        if(userId1->length == 0 && userId2->length == 0) {
400
            /* Both users are anonymous.
401
             * For anonymous users, the OPC UA specification requires
402
             * checking the ApplicationUri from the clientDescription
403
             * to verify that the same application is transferring the
404
             * subscription (e.g. after a network interruption or client
405
             * crash with reconnect on a different SecureChannel).
406
             *
407
             * Additionally, on unsecure connections (SecurityPolicy#None)
408
             * the ApplicationUri is not verified against a certificate,
409
             * so the transfer must be rejected. */
410
411
            /* First check: Both sessions must use a secure channel
412
             * (not SecurityPolicy#None). The securityPolicyUri was
413
             * stored as a session attribute during ActivateSession. */
414
0
            UA_Variant session1SpUri;
415
0
            UA_Variant_init(&session1SpUri);
416
0
            UA_Server_getSessionAttribute(server, oldSessionId,
417
0
                                          UA_QUALIFIEDNAME(0, "channelSecurityPolicyUri"),
418
0
                                          &session1SpUri);
419
0
            UA_Variant session2SpUri;
420
0
            UA_Variant_init(&session2SpUri);
421
0
            UA_Server_getSessionAttribute(server, newSessionId,
422
0
                                          UA_QUALIFIEDNAME(0, "channelSecurityPolicyUri"),
423
0
                                          &session2SpUri);
424
425
0
            UA_Boolean bothSecure = false;
426
0
            if(session1SpUri.type == &UA_TYPES[UA_TYPES_STRING] &&
427
0
               session2SpUri.type == &UA_TYPES[UA_TYPES_STRING]) {
428
0
                UA_String *spUri1 = (UA_String*)session1SpUri.data;
429
0
                UA_String *spUri2 = (UA_String*)session2SpUri.data;
430
                /* Reject if either session uses SecurityPolicy#None */
431
0
                if(!UA_String_equal(spUri1, &UA_SECURITY_POLICY_NONE_URI) &&
432
0
                   !UA_String_equal(spUri2, &UA_SECURITY_POLICY_NONE_URI)) {
433
0
                    bothSecure = true;
434
0
                }
435
0
            }
436
437
0
            UA_Variant_clear(&session1SpUri);
438
0
            UA_Variant_clear(&session2SpUri);
439
440
            /* Second check: If both channels are secure, compare the
441
             * ApplicationUri from the clientDescription. On secure
442
             * connections the ApplicationUri is validated against
443
             * the client certificate during CreateSession. */
444
0
            if(bothSecure) {
445
0
                UA_Variant session1Desc;
446
0
                UA_Variant_init(&session1Desc);
447
0
                UA_Server_getSessionAttribute(server, oldSessionId,
448
0
                                              UA_QUALIFIEDNAME(0, "clientDescription"),
449
0
                                              &session1Desc);
450
0
                UA_Variant session2Desc;
451
0
                UA_Variant_init(&session2Desc);
452
0
                UA_Server_getSessionAttribute(server, newSessionId,
453
0
                                              UA_QUALIFIEDNAME(0, "clientDescription"),
454
0
                                              &session2Desc);
455
456
0
                if(session1Desc.type == &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION] &&
457
0
                   session2Desc.type == &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]) {
458
0
                    UA_ApplicationDescription *desc1 =
459
0
                        (UA_ApplicationDescription*)session1Desc.data;
460
0
                    UA_ApplicationDescription *desc2 =
461
0
                        (UA_ApplicationDescription*)session2Desc.data;
462
0
                    if(desc1->applicationUri.length > 0 &&
463
0
                       desc2->applicationUri.length > 0 &&
464
0
                       UA_String_equal(&desc1->applicationUri,
465
0
                                       &desc2->applicationUri)) {
466
0
                        result = true;
467
0
                    }
468
0
                }
469
470
0
                UA_Variant_clear(&session1Desc);
471
0
                UA_Variant_clear(&session2Desc);
472
0
            }
473
0
        } else if(UA_String_equal(userId1, userId2)) {
474
            /* Same authenticated user - allow transfer */
475
0
            result = true;
476
0
        }
477
0
    }
478
    
479
0
    UA_Variant_clear(&session1UserId);
480
0
    UA_Variant_clear(&session2UserId);
481
    
482
0
    return result;
483
0
}
484
#endif
485
486
#ifdef UA_ENABLE_HISTORIZING
487
/* OPC UA Part 3, Table 8: InsertHistory / ModifyHistory permissions.
488
 * INSERT -> InsertHistory, REPLACE/UPDATE -> ModifyHistory. */
489
static UA_Boolean
490
allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
491
                                     const UA_NodeId *sessionId, void *sessionContext,
492
                                     const UA_NodeId *nodeId,
493
                                     UA_PerformUpdateType performInsertReplace,
494
0
                                     const UA_DataValue *value) {
495
#ifdef UA_ENABLE_RBAC
496
    UA_PermissionType effectivePerms = 0;
497
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
498
                                                          nodeId, &effectivePerms);
499
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
500
        return true;
501
    if(performInsertReplace == UA_PERFORMUPDATETYPE_INSERT)
502
        return (effectivePerms & UA_PERMISSIONTYPE_INSERTHISTORY) != 0;
503
    else if(performInsertReplace == UA_PERFORMUPDATETYPE_REPLACE ||
504
            performInsertReplace == UA_PERFORMUPDATETYPE_UPDATE)
505
        return (effectivePerms & UA_PERMISSIONTYPE_MODIFYHISTORY) != 0;
506
    return true;
507
#else
508
0
    return true;
509
0
#endif
510
0
}
511
512
/* OPC UA Part 3, Table 8: DeleteHistory permission. */
513
static UA_Boolean
514
allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
515
                                            const UA_NodeId *sessionId, void *sessionContext,
516
                                            const UA_NodeId *nodeId,
517
                                            UA_DateTime startTimestamp,
518
                                            UA_DateTime endTimestamp,
519
0
                                            bool isDeleteModified) {
520
#ifdef UA_ENABLE_RBAC
521
    UA_PermissionType effectivePerms = 0;
522
    UA_StatusCode res = UA_Server_getEffectivePermissions(server, sessionId,
523
                                                          nodeId, &effectivePerms);
524
    if(res != UA_STATUSCODE_GOOD || effectivePerms == 0xFFFFFFFF)
525
        return true;
526
    return (effectivePerms & UA_PERMISSIONTYPE_DELETEHISTORY) != 0;
527
#else
528
0
    return true;
529
0
#endif
530
0
}
531
#endif
532
533
/***************************************/
534
/* Create Delete Access Control Plugin */
535
/***************************************/
536
537
18.7k
static void clear_default(UA_AccessControl *ac) {
538
18.7k
    UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
539
18.7k
                    ac->userTokenPoliciesSize,
540
18.7k
                    &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
541
18.7k
    ac->userTokenPolicies = NULL;
542
18.7k
    ac->userTokenPoliciesSize = 0;
543
544
18.7k
    AccessControlContext *context = (AccessControlContext*)ac->context;
545
546
18.7k
    if (context) {
547
18.7k
        for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
548
0
            UA_String_clear(&context->usernamePasswordLogin[i].username);
549
0
            UA_ByteString_clear(&context->usernamePasswordLogin[i].password);
550
0
        }
551
18.7k
        if(context->usernamePasswordLoginSize > 0)
552
0
            UA_free(context->usernamePasswordLogin);
553
554
18.7k
        UA_free(ac->context);
555
18.7k
        ac->context = NULL;
556
18.7k
    }
557
18.7k
}
558
559
UA_StatusCode
560
UA_AccessControl_default(UA_ServerConfig *config,
561
                         UA_Boolean allowAnonymous,
562
                         const UA_String *userTokenPolicyUri,
563
                         size_t usernamePasswordLoginSize,
564
18.7k
                         const UA_UsernamePasswordLogin *usernamePasswordLogin) {
565
18.7k
    UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
566
18.7k
                   "AccessControl: Unconfigured AccessControl. Users have all permissions.");
567
18.7k
    UA_AccessControl *ac = &config->accessControl;
568
569
18.7k
    if(ac->clear)
570
0
        ac->clear(ac);
571
572
18.7k
    ac->clear = clear_default;
573
18.7k
    ac->activateSession = activateSession_default;
574
18.7k
    ac->closeSession = closeSession_default;
575
18.7k
    ac->getUserRightsMask = getUserRightsMask_default;
576
18.7k
    ac->getUserAccessLevel = getUserAccessLevel_default;
577
18.7k
    ac->getUserExecutable = getUserExecutable_default;
578
18.7k
    ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
579
18.7k
    ac->allowAddNode = allowAddNode_default;
580
18.7k
    ac->allowAddReference = allowAddReference_default;
581
18.7k
    ac->allowBrowseNode = allowBrowseNode_default;
582
583
18.7k
#ifdef UA_ENABLE_SUBSCRIPTIONS
584
18.7k
    ac->allowCreateSubscription = allowCreateSubscription_default;
585
18.7k
    ac->allowTransferSubscription = allowTransferSubscription_default;
586
18.7k
#endif
587
588
18.7k
#ifdef UA_ENABLE_HISTORIZING
589
18.7k
    ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
590
18.7k
    ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
591
18.7k
#endif
592
593
18.7k
    ac->allowDeleteNode = allowDeleteNode_default;
594
18.7k
    ac->allowDeleteReference = allowDeleteReference_default;
595
596
18.7k
    AccessControlContext *context = (AccessControlContext*)
597
18.7k
            UA_malloc(sizeof(AccessControlContext));
598
18.7k
    if(!context)
599
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
600
18.7k
    memset(context, 0, sizeof(AccessControlContext));
601
18.7k
    ac->context = context;
602
603
    /* Allow anonymous? */
604
18.7k
    context->allowAnonymous = allowAnonymous;
605
18.7k
    if(allowAnonymous) {
606
18.7k
        UA_LOG_INFO(config->logging, UA_LOGCATEGORY_SERVER,
607
18.7k
                    "AccessControl: Anonymous login is enabled");
608
18.7k
    }
609
610
    /* Copy username/password to the access control plugin */
611
18.7k
    if(usernamePasswordLoginSize > 0) {
612
0
        context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
613
0
            UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
614
0
        if(!context->usernamePasswordLogin)
615
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
616
0
        context->usernamePasswordLoginSize = usernamePasswordLoginSize;
617
0
        for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
618
0
            UA_String_copy(&usernamePasswordLogin[i].username,
619
0
                           &context->usernamePasswordLogin[i].username);
620
0
            UA_ByteString_copy(&usernamePasswordLogin[i].password,
621
0
                           &context->usernamePasswordLogin[i].password);
622
0
        }
623
0
    }
624
625
18.7k
    size_t numOfPolcies = 1;
626
18.7k
    if(!userTokenPolicyUri) {
627
18.7k
        if(config->securityPoliciesSize > 0)
628
18.7k
            numOfPolcies = config->securityPoliciesSize;
629
0
        else {
630
0
            UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
631
0
                           "No security policies defined for the secure channel.");
632
0
            return UA_STATUSCODE_BADINTERNALERROR;
633
0
        }
634
18.7k
    }
635
636
    /* Set the allowed policies */
637
18.7k
    size_t policies = 0;
638
18.7k
    if(allowAnonymous)
639
18.7k
        policies++;
640
18.7k
    if(usernamePasswordLoginSize > 0)
641
0
        policies++;
642
18.7k
    if(config->sessionPKI.verifyCertificate)
643
18.7k
        policies++;
644
18.7k
    ac->userTokenPoliciesSize = 0;
645
18.7k
    ac->userTokenPolicies = (UA_UserTokenPolicy *)
646
18.7k
        UA_Array_new(policies * numOfPolcies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
647
18.7k
    if(!ac->userTokenPolicies)
648
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
649
18.7k
    ac->userTokenPoliciesSize = policies * numOfPolcies;
650
651
18.7k
    if(policies == 0) {
652
0
        UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
653
0
                       "No allowed policies set.");
654
0
        return UA_STATUSCODE_GOOD;
655
0
    }
656
657
18.7k
    const UA_String *utpUri = NULL;
658
18.7k
    policies = 0;
659
37.5k
    for(size_t i = 0; i < numOfPolcies; i++) {
660
18.7k
        if(userTokenPolicyUri) {
661
0
            utpUri = userTokenPolicyUri;
662
18.7k
        } else {
663
18.7k
            utpUri = &config->securityPolicies[i].policyUri;
664
18.7k
        }
665
18.7k
        if(allowAnonymous) {
666
18.7k
            ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
667
18.7k
            ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
668
18.7k
            UA_String_copy(utpUri,
669
18.7k
                               &ac->userTokenPolicies[policies].securityPolicyUri);
670
18.7k
            policies++;
671
18.7k
        }
672
673
18.7k
        if(config->sessionPKI.verifyCertificate) {
674
18.7k
            ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_CERTIFICATE;
675
18.7k
            ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(CERTIFICATE_POLICY);
676
#if UA_LOGLEVEL <= 400
677
            if(UA_String_equal(utpUri, &UA_SECURITY_POLICY_NONE_URI)) {
678
                UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
679
                               "x509 Certificate Authentication configured, "
680
                               "but no encrypting SecurityPolicy. "
681
                               "This can leak credentials on the network.");
682
            }
683
#endif
684
18.7k
            UA_String_copy(utpUri,
685
18.7k
                               &ac->userTokenPolicies[policies].securityPolicyUri);
686
18.7k
            policies++;
687
18.7k
        }
688
689
18.7k
        if(usernamePasswordLoginSize > 0) {
690
0
            ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
691
0
            ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
692
#if UA_LOGLEVEL <= 400
693
            if(UA_String_equal(utpUri, &UA_SECURITY_POLICY_NONE_URI)) {
694
                UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
695
                               "Username/Password Authentication configured, "
696
                               "but no encrypting SecurityPolicy. "
697
                               "This can leak credentials on the network.");
698
            }
699
#endif
700
0
            UA_String_copy(utpUri,
701
0
                               &ac->userTokenPolicies[policies].securityPolicyUri);
702
0
            policies++;
703
0
        }
704
18.7k
    }
705
18.7k
    return UA_STATUSCODE_GOOD;
706
18.7k
}
707
708
UA_StatusCode
709
UA_AccessControl_defaultWithLoginCallback(UA_ServerConfig *config,
710
                                          UA_Boolean allowAnonymous,
711
                                          const UA_String *userTokenPolicyUri,
712
                                          size_t usernamePasswordLoginSize,
713
                                          const UA_UsernamePasswordLogin *usernamePasswordLogin,
714
                                          UA_UsernamePasswordLoginCallback loginCallback,
715
0
                                          void *loginContext) {
716
0
    AccessControlContext *context;
717
0
    UA_StatusCode sc =
718
0
        UA_AccessControl_default(config, allowAnonymous, userTokenPolicyUri,
719
0
                                 usernamePasswordLoginSize, usernamePasswordLogin);
720
0
    if(sc != UA_STATUSCODE_GOOD)
721
0
        return sc;
722
723
0
    context = (AccessControlContext *)config->accessControl.context;
724
0
    context->loginCallback = loginCallback;
725
0
    context->loginContext = loginContext;
726
727
0
    return UA_STATUSCODE_GOOD;
728
0
}