Coverage Report

Created: 2026-07-16 06:23

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