Coverage Report

Created: 2026-07-16 06:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/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
/* Example access control management. Anonymous and username / password login.
12
 * The access rights are maximally permissive.
13
 *
14
 * FOR PRODUCTION USE, THIS EXAMPLE PLUGIN SHOULD BE REPLACED WITH LESS
15
 * PERMISSIVE ACCESS CONTROL.
16
 *
17
 * For TransferSubscriptions, we check whether the transfer happens between
18
 * Sessions for the same user. */
19
20
typedef struct {
21
    UA_Boolean allowAnonymous;
22
    size_t usernamePasswordLoginSize;
23
    UA_UsernamePasswordLogin *usernamePasswordLogin;
24
    UA_UsernamePasswordLoginCallback loginCallback;
25
    void *loginContext;
26
    UA_CertificateGroup verifyX509;
27
} AccessControlContext;
28
29
#define ANONYMOUS_POLICY "open62541-anonymous-policy"
30
#define CERTIFICATE_POLICY "open62541-certificate-policy"
31
#define USERNAME_POLICY "open62541-username-policy"
32
33
/************************/
34
/* Access Control Logic */
35
/************************/
36
37
static UA_StatusCode
38
activateSession_default(UA_Server *server, UA_AccessControl *ac,
39
                        const UA_EndpointDescription *endpointDescription,
40
                        const UA_ByteString *secureChannelRemoteCertificate,
41
                        const UA_NodeId *sessionId,
42
                        const UA_ExtensionObject *userIdentityToken,
43
975
                        void **sessionContext) {
44
975
    AccessControlContext *context = (AccessControlContext*)ac->context;
45
46
    /* The empty token is interpreted as anonymous */
47
975
    UA_AnonymousIdentityToken anonToken;
48
975
    UA_ExtensionObject tmpIdentity;
49
975
    if(userIdentityToken->encoding == UA_EXTENSIONOBJECT_ENCODED_NOBODY) {
50
975
        UA_AnonymousIdentityToken_init(&anonToken);
51
975
        UA_ExtensionObject_init(&tmpIdentity);
52
975
        UA_ExtensionObject_setValueNoDelete(&tmpIdentity,
53
975
                                            &anonToken,
54
975
                                            &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]);
55
975
        userIdentityToken = &tmpIdentity;
56
975
    }
57
58
    /* Could the token be decoded? */
59
975
    if(userIdentityToken->encoding < UA_EXTENSIONOBJECT_DECODED)
60
0
        return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
61
62
975
    const UA_DataType *tokenType = userIdentityToken->content.decoded.type;
63
975
    if(tokenType == &UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN]) {
64
        /* Anonymous login */
65
975
        if(!context->allowAnonymous)
66
0
            return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
67
975
        if(context->loginCallback) {
68
0
            UA_StatusCode res =
69
0
                context->loginCallback(&UA_STRING_NULL, &UA_BYTESTRING_NULL,
70
0
                                       context->usernamePasswordLoginSize,
71
0
                                       context->usernamePasswordLogin,
72
0
                                       sessionContext, context->loginContext);
73
0
            if(res != UA_STATUSCODE_GOOD)
74
0
                return UA_STATUSCODE_BADUSERACCESSDENIED;
75
0
        }
76
975
    } else if(tokenType == &UA_TYPES[UA_TYPES_USERNAMEIDENTITYTOKEN]) {
77
        /* Username and password */
78
0
        const UA_UserNameIdentityToken *userToken = (UA_UserNameIdentityToken*)
79
0
            userIdentityToken->content.decoded.data;
80
81
        /* Empty username and password */
82
0
        if(userToken->userName.length == 0 && userToken->password.length == 0)
83
0
            return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
84
85
        /* Try to match username/pw */
86
0
        if(context->loginCallback) {
87
            /* Configured callback */
88
0
            UA_StatusCode res =
89
0
                context->loginCallback(&userToken->userName, &userToken->password,
90
0
                                       context->usernamePasswordLoginSize,
91
0
                                       context->usernamePasswordLogin,
92
0
                                       sessionContext, context->loginContext);
93
0
            if(res != UA_STATUSCODE_GOOD)
94
0
                return UA_STATUSCODE_BADUSERACCESSDENIED;
95
0
        } else {
96
            /* Compare against the configured list  */
97
0
            UA_Boolean match = false;
98
0
            for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
99
0
                UA_UsernamePasswordLogin *upl = &context->usernamePasswordLogin[i];
100
0
                if(!UA_String_equal(&userToken->userName, &upl->username))
101
0
                   continue;
102
0
                if(userToken->password.length != upl->password.length)
103
0
                    continue;
104
0
                if(!UA_constantTimeEqual(userToken->password.data,
105
0
                                         upl->password.data,
106
0
                                         upl->password.length))
107
0
                    continue;
108
0
                match = true;
109
0
                break;
110
0
            }
111
0
            if(!match)
112
0
                return UA_STATUSCODE_BADUSERACCESSDENIED;
113
0
        }
114
0
    } else if(tokenType == &UA_TYPES[UA_TYPES_X509IDENTITYTOKEN]) {
115
        /* x509 certificate was already validated against the sessionPKI in the
116
         * server */
117
0
    } else {
118
        /* Unsupported token type */
119
0
        return UA_STATUSCODE_BADIDENTITYTOKENINVALID;
120
0
    }
121
122
    /* Store the endpoint's SecurityPolicyUri as a custom session attribute.
123
     * This is needed later in allowTransferSubscription_default to determine
124
     * whether the session was established over a secure channel. */
125
975
    if(endpointDescription) {
126
975
        UA_Variant spUri;
127
975
        UA_Variant_setScalar(&spUri, (void*)(uintptr_t)&endpointDescription->securityPolicyUri,
128
975
                             &UA_TYPES[UA_TYPES_STRING]);
129
975
        UA_Server_setSessionAttribute(server, sessionId,
130
975
                                      UA_QUALIFIEDNAME(0, "channelSecurityPolicyUri"),
131
975
                                      &spUri);
132
975
    }
133
134
975
    return UA_STATUSCODE_GOOD;
135
975
}
136
137
static void
138
closeSession_default(UA_Server *server, UA_AccessControl *ac,
139
5.52k
                     const UA_NodeId *sessionId, void *sessionContext) {
140
5.52k
}
141
142
static UA_UInt32
143
getUserRightsMask_default(UA_Server *server, UA_AccessControl *ac,
144
                          const UA_NodeId *sessionId, void *sessionContext,
145
0
                          const UA_NodeId *nodeId, void *nodeContext) {
146
0
    return 0xFFFFFFFF;
147
0
}
148
149
static UA_Byte
150
getUserAccessLevel_default(UA_Server *server, UA_AccessControl *ac,
151
                           const UA_NodeId *sessionId, void *sessionContext,
152
0
                           const UA_NodeId *nodeId, void *nodeContext) {
153
0
    return 0xFF;
154
0
}
155
156
static UA_Boolean
157
getUserExecutable_default(UA_Server *server, UA_AccessControl *ac,
158
                          const UA_NodeId *sessionId, void *sessionContext,
159
0
                          const UA_NodeId *methodId, void *methodContext) {
160
0
    return true;
161
0
}
162
163
static UA_Boolean
164
getUserExecutableOnObject_default(UA_Server *server, UA_AccessControl *ac,
165
                                  const UA_NodeId *sessionId, void *sessionContext,
166
                                  const UA_NodeId *methodId, void *methodContext,
167
0
                                  const UA_NodeId *objectId, void *objectContext) {
168
0
    return true;
169
0
}
170
171
static UA_Boolean
172
allowAddNode_default(UA_Server *server, UA_AccessControl *ac,
173
                     const UA_NodeId *sessionId, void *sessionContext,
174
0
                     const UA_AddNodesItem *item) {
175
0
    return true;
176
0
}
177
178
static UA_Boolean
179
allowAddReference_default(UA_Server *server, UA_AccessControl *ac,
180
                          const UA_NodeId *sessionId, void *sessionContext,
181
0
                          const UA_AddReferencesItem *item) {
182
0
    return true;
183
0
}
184
185
static UA_Boolean
186
allowDeleteNode_default(UA_Server *server, UA_AccessControl *ac,
187
                        const UA_NodeId *sessionId, void *sessionContext,
188
149
                        const UA_DeleteNodesItem *item) {
189
149
    return true;
190
149
}
191
192
static UA_Boolean
193
allowDeleteReference_default(UA_Server *server, UA_AccessControl *ac,
194
                             const UA_NodeId *sessionId, void *sessionContext,
195
121k
                             const UA_DeleteReferencesItem *item) {
196
121k
    return true;
197
121k
}
198
199
static UA_Boolean
200
allowBrowseNode_default(UA_Server *server, UA_AccessControl *ac,
201
                        const UA_NodeId *sessionId, void *sessionContext,
202
0
                        const UA_NodeId *nodeId, void *nodeContext) {
203
0
    return true;
204
0
}
205
206
#ifdef UA_ENABLE_SUBSCRIPTIONS
207
static UA_Boolean
208
allowTransferSubscription_default(UA_Server *server, UA_AccessControl *ac,
209
                                  const UA_NodeId *oldSessionId, void *oldSessionContext,
210
0
                                  const UA_NodeId *newSessionId, void *newSessionContext) {
211
0
    if(!oldSessionId)
212
0
        return false;
213
    
214
    /* Get clientUserId for both sessions */
215
0
    UA_Variant session1UserId;
216
0
    UA_Variant_init(&session1UserId);
217
0
    UA_Server_getSessionAttribute(server, oldSessionId,
218
0
                                  UA_QUALIFIEDNAME(0, "clientUserId"),
219
0
                                  &session1UserId);
220
0
    UA_Variant session2UserId;
221
0
    UA_Variant_init(&session2UserId);
222
0
    UA_Server_getSessionAttribute(server, newSessionId,
223
0
                                  UA_QUALIFIEDNAME(0, "clientUserId"),
224
0
                                  &session2UserId);
225
226
    /* clientUserId is always a String type */
227
0
    UA_Boolean result = false;
228
0
    if(session1UserId.type == &UA_TYPES[UA_TYPES_STRING] &&
229
0
       session2UserId.type == &UA_TYPES[UA_TYPES_STRING]) {
230
0
        UA_String *userId1 = (UA_String*)session1UserId.data;
231
0
        UA_String *userId2 = (UA_String*)session2UserId.data;
232
        
233
0
        if(userId1->length == 0 && userId2->length == 0) {
234
            /* Both users are anonymous.
235
             * For anonymous users, the OPC UA specification requires
236
             * checking the ApplicationUri from the clientDescription
237
             * to verify that the same application is transferring the
238
             * subscription (e.g. after a network interruption or client
239
             * crash with reconnect on a different SecureChannel).
240
             *
241
             * Additionally, on unsecure connections (SecurityPolicy#None)
242
             * the ApplicationUri is not verified against a certificate,
243
             * so the transfer must be rejected. */
244
245
            /* First check: Both sessions must use a secure channel
246
             * (not SecurityPolicy#None). The securityPolicyUri was
247
             * stored as a session attribute during ActivateSession. */
248
0
            UA_Variant session1SpUri;
249
0
            UA_Variant_init(&session1SpUri);
250
0
            UA_Server_getSessionAttribute(server, oldSessionId,
251
0
                                          UA_QUALIFIEDNAME(0, "channelSecurityPolicyUri"),
252
0
                                          &session1SpUri);
253
0
            UA_Variant session2SpUri;
254
0
            UA_Variant_init(&session2SpUri);
255
0
            UA_Server_getSessionAttribute(server, newSessionId,
256
0
                                          UA_QUALIFIEDNAME(0, "channelSecurityPolicyUri"),
257
0
                                          &session2SpUri);
258
259
0
            UA_Boolean bothSecure = false;
260
0
            if(session1SpUri.type == &UA_TYPES[UA_TYPES_STRING] &&
261
0
               session2SpUri.type == &UA_TYPES[UA_TYPES_STRING]) {
262
0
                UA_String *spUri1 = (UA_String*)session1SpUri.data;
263
0
                UA_String *spUri2 = (UA_String*)session2SpUri.data;
264
                /* Reject if either session uses SecurityPolicy#None */
265
0
                if(!UA_String_equal(spUri1, &UA_SECURITY_POLICY_NONE_URI) &&
266
0
                   !UA_String_equal(spUri2, &UA_SECURITY_POLICY_NONE_URI)) {
267
0
                    bothSecure = true;
268
0
                }
269
0
            }
270
271
0
            UA_Variant_clear(&session1SpUri);
272
0
            UA_Variant_clear(&session2SpUri);
273
274
            /* Second check: If both channels are secure, compare the
275
             * ApplicationUri from the clientDescription. On secure
276
             * connections the ApplicationUri is validated against
277
             * the client certificate during CreateSession. */
278
0
            if(bothSecure) {
279
0
                UA_Variant session1Desc;
280
0
                UA_Variant_init(&session1Desc);
281
0
                UA_Server_getSessionAttribute(server, oldSessionId,
282
0
                                              UA_QUALIFIEDNAME(0, "clientDescription"),
283
0
                                              &session1Desc);
284
0
                UA_Variant session2Desc;
285
0
                UA_Variant_init(&session2Desc);
286
0
                UA_Server_getSessionAttribute(server, newSessionId,
287
0
                                              UA_QUALIFIEDNAME(0, "clientDescription"),
288
0
                                              &session2Desc);
289
290
0
                if(session1Desc.type == &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION] &&
291
0
                   session2Desc.type == &UA_TYPES[UA_TYPES_APPLICATIONDESCRIPTION]) {
292
0
                    UA_ApplicationDescription *desc1 =
293
0
                        (UA_ApplicationDescription*)session1Desc.data;
294
0
                    UA_ApplicationDescription *desc2 =
295
0
                        (UA_ApplicationDescription*)session2Desc.data;
296
0
                    if(desc1->applicationUri.length > 0 &&
297
0
                       desc2->applicationUri.length > 0 &&
298
0
                       UA_String_equal(&desc1->applicationUri,
299
0
                                       &desc2->applicationUri)) {
300
0
                        result = true;
301
0
                    }
302
0
                }
303
304
0
                UA_Variant_clear(&session1Desc);
305
0
                UA_Variant_clear(&session2Desc);
306
0
            }
307
0
        } else if(UA_String_equal(userId1, userId2)) {
308
            /* Same authenticated user - allow transfer */
309
0
            result = true;
310
0
        }
311
0
    }
312
    
313
0
    UA_Variant_clear(&session1UserId);
314
0
    UA_Variant_clear(&session2UserId);
315
    
316
0
    return result;
317
0
}
318
#endif
319
320
#ifdef UA_ENABLE_HISTORIZING
321
static UA_Boolean
322
allowHistoryUpdateUpdateData_default(UA_Server *server, UA_AccessControl *ac,
323
                                     const UA_NodeId *sessionId, void *sessionContext,
324
                                     const UA_NodeId *nodeId,
325
                                     UA_PerformUpdateType performInsertReplace,
326
0
                                     const UA_DataValue *value) {
327
0
    return true;
328
0
}
329
330
static UA_Boolean
331
allowHistoryUpdateDeleteRawModified_default(UA_Server *server, UA_AccessControl *ac,
332
                                            const UA_NodeId *sessionId, void *sessionContext,
333
                                            const UA_NodeId *nodeId,
334
                                            UA_DateTime startTimestamp,
335
                                            UA_DateTime endTimestamp,
336
0
                                            bool isDeleteModified) {
337
0
    return true;
338
0
}
339
#endif
340
341
/***************************************/
342
/* Create Delete Access Control Plugin */
343
/***************************************/
344
345
13.5k
static void clear_default(UA_AccessControl *ac) {
346
13.5k
    UA_Array_delete((void*)(uintptr_t)ac->userTokenPolicies,
347
13.5k
                    ac->userTokenPoliciesSize,
348
13.5k
                    &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
349
13.5k
    ac->userTokenPolicies = NULL;
350
13.5k
    ac->userTokenPoliciesSize = 0;
351
352
13.5k
    AccessControlContext *context = (AccessControlContext*)ac->context;
353
354
13.5k
    if (context) {
355
13.5k
        for(size_t i = 0; i < context->usernamePasswordLoginSize; i++) {
356
0
            UA_String_clear(&context->usernamePasswordLogin[i].username);
357
0
            UA_ByteString_clear(&context->usernamePasswordLogin[i].password);
358
0
        }
359
13.5k
        if(context->usernamePasswordLoginSize > 0)
360
0
            UA_free(context->usernamePasswordLogin);
361
362
13.5k
        UA_free(ac->context);
363
13.5k
        ac->context = NULL;
364
13.5k
    }
365
13.5k
}
366
367
UA_StatusCode
368
UA_AccessControl_default(UA_ServerConfig *config,
369
                         UA_Boolean allowAnonymous,
370
                         const UA_String *userTokenPolicyUri,
371
                         size_t usernamePasswordLoginSize,
372
13.5k
                         const UA_UsernamePasswordLogin *usernamePasswordLogin) {
373
13.5k
    UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
374
13.5k
                   "AccessControl: Unconfigured AccessControl. Users have all permissions.");
375
13.5k
    UA_AccessControl *ac = &config->accessControl;
376
377
13.5k
    if(ac->clear)
378
0
        ac->clear(ac);
379
380
13.5k
    ac->clear = clear_default;
381
13.5k
    ac->activateSession = activateSession_default;
382
13.5k
    ac->closeSession = closeSession_default;
383
13.5k
    ac->getUserRightsMask = getUserRightsMask_default;
384
13.5k
    ac->getUserAccessLevel = getUserAccessLevel_default;
385
13.5k
    ac->getUserExecutable = getUserExecutable_default;
386
13.5k
    ac->getUserExecutableOnObject = getUserExecutableOnObject_default;
387
13.5k
    ac->allowAddNode = allowAddNode_default;
388
13.5k
    ac->allowAddReference = allowAddReference_default;
389
13.5k
    ac->allowBrowseNode = allowBrowseNode_default;
390
391
13.5k
#ifdef UA_ENABLE_SUBSCRIPTIONS
392
13.5k
    ac->allowTransferSubscription = allowTransferSubscription_default;
393
13.5k
#endif
394
395
13.5k
#ifdef UA_ENABLE_HISTORIZING
396
13.5k
    ac->allowHistoryUpdateUpdateData = allowHistoryUpdateUpdateData_default;
397
13.5k
    ac->allowHistoryUpdateDeleteRawModified = allowHistoryUpdateDeleteRawModified_default;
398
13.5k
#endif
399
400
13.5k
    ac->allowDeleteNode = allowDeleteNode_default;
401
13.5k
    ac->allowDeleteReference = allowDeleteReference_default;
402
403
13.5k
    AccessControlContext *context = (AccessControlContext*)
404
13.5k
            UA_malloc(sizeof(AccessControlContext));
405
13.5k
    if(!context)
406
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
407
13.5k
    memset(context, 0, sizeof(AccessControlContext));
408
13.5k
    ac->context = context;
409
410
    /* Allow anonymous? */
411
13.5k
    context->allowAnonymous = allowAnonymous;
412
13.5k
    if(allowAnonymous) {
413
13.5k
        UA_LOG_INFO(config->logging, UA_LOGCATEGORY_SERVER,
414
13.5k
                    "AccessControl: Anonymous login is enabled");
415
13.5k
    }
416
417
    /* Copy username/password to the access control plugin */
418
13.5k
    if(usernamePasswordLoginSize > 0) {
419
0
        context->usernamePasswordLogin = (UA_UsernamePasswordLogin*)
420
0
            UA_malloc(usernamePasswordLoginSize * sizeof(UA_UsernamePasswordLogin));
421
0
        if(!context->usernamePasswordLogin)
422
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
423
0
        context->usernamePasswordLoginSize = usernamePasswordLoginSize;
424
0
        for(size_t i = 0; i < usernamePasswordLoginSize; i++) {
425
0
            UA_String_copy(&usernamePasswordLogin[i].username,
426
0
                           &context->usernamePasswordLogin[i].username);
427
0
            UA_ByteString_copy(&usernamePasswordLogin[i].password,
428
0
                           &context->usernamePasswordLogin[i].password);
429
0
        }
430
0
    }
431
432
13.5k
    size_t numOfPolcies = 1;
433
13.5k
    if(!userTokenPolicyUri) {
434
13.5k
        if(config->securityPoliciesSize > 0)
435
13.5k
            numOfPolcies = config->securityPoliciesSize;
436
0
        else {
437
0
            UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
438
0
                           "No security policies defined for the secure channel.");
439
0
            return UA_STATUSCODE_BADINTERNALERROR;
440
0
        }
441
13.5k
    }
442
443
    /* Set the allowed policies */
444
13.5k
    size_t policies = 0;
445
13.5k
    if(allowAnonymous)
446
13.5k
        policies++;
447
13.5k
    if(usernamePasswordLoginSize > 0)
448
0
        policies++;
449
13.5k
    if(config->sessionPKI.verifyCertificate)
450
13.5k
        policies++;
451
13.5k
    ac->userTokenPoliciesSize = 0;
452
13.5k
    ac->userTokenPolicies = (UA_UserTokenPolicy *)
453
13.5k
        UA_Array_new(policies * numOfPolcies, &UA_TYPES[UA_TYPES_USERTOKENPOLICY]);
454
13.5k
    if(!ac->userTokenPolicies)
455
0
        return UA_STATUSCODE_BADOUTOFMEMORY;
456
13.5k
    ac->userTokenPoliciesSize = policies * numOfPolcies;
457
458
13.5k
    if(policies == 0) {
459
0
        UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
460
0
                       "No allowed policies set.");
461
0
        return UA_STATUSCODE_GOOD;
462
0
    }
463
464
13.5k
    const UA_String *utpUri = NULL;
465
13.5k
    policies = 0;
466
27.0k
    for(size_t i = 0; i < numOfPolcies; i++) {
467
13.5k
        if(userTokenPolicyUri) {
468
0
            utpUri = userTokenPolicyUri;
469
13.5k
        } else {
470
13.5k
            utpUri = &config->securityPolicies[i].policyUri;
471
13.5k
        }
472
13.5k
        if(allowAnonymous) {
473
13.5k
            ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_ANONYMOUS;
474
13.5k
            ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(ANONYMOUS_POLICY);
475
13.5k
            UA_String_copy(utpUri,
476
13.5k
                               &ac->userTokenPolicies[policies].securityPolicyUri);
477
13.5k
            policies++;
478
13.5k
        }
479
480
13.5k
        if(config->sessionPKI.verifyCertificate) {
481
13.5k
            ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_CERTIFICATE;
482
13.5k
            ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(CERTIFICATE_POLICY);
483
#if UA_LOGLEVEL <= 400
484
            if(UA_String_equal(utpUri, &UA_SECURITY_POLICY_NONE_URI)) {
485
                UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
486
                               "x509 Certificate Authentication configured, "
487
                               "but no encrypting SecurityPolicy. "
488
                               "This can leak credentials on the network.");
489
            }
490
#endif
491
13.5k
            UA_String_copy(utpUri,
492
13.5k
                               &ac->userTokenPolicies[policies].securityPolicyUri);
493
13.5k
            policies++;
494
13.5k
        }
495
496
13.5k
        if(usernamePasswordLoginSize > 0) {
497
0
            ac->userTokenPolicies[policies].tokenType = UA_USERTOKENTYPE_USERNAME;
498
0
            ac->userTokenPolicies[policies].policyId = UA_STRING_ALLOC(USERNAME_POLICY);
499
#if UA_LOGLEVEL <= 400
500
            if(UA_String_equal(utpUri, &UA_SECURITY_POLICY_NONE_URI)) {
501
                UA_LOG_WARNING(config->logging, UA_LOGCATEGORY_SERVER,
502
                               "Username/Password Authentication configured, "
503
                               "but no encrypting SecurityPolicy. "
504
                               "This can leak credentials on the network.");
505
            }
506
#endif
507
0
            UA_String_copy(utpUri,
508
0
                               &ac->userTokenPolicies[policies].securityPolicyUri);
509
0
            policies++;
510
0
        }
511
13.5k
    }
512
13.5k
    return UA_STATUSCODE_GOOD;
513
13.5k
}
514
515
UA_StatusCode
516
UA_AccessControl_defaultWithLoginCallback(UA_ServerConfig *config,
517
                                          UA_Boolean allowAnonymous,
518
                                          const UA_String *userTokenPolicyUri,
519
                                          size_t usernamePasswordLoginSize,
520
                                          const UA_UsernamePasswordLogin *usernamePasswordLogin,
521
                                          UA_UsernamePasswordLoginCallback loginCallback,
522
0
                                          void *loginContext) {
523
0
    AccessControlContext *context;
524
0
    UA_StatusCode sc =
525
0
        UA_AccessControl_default(config, allowAnonymous, userTokenPolicyUri,
526
0
                                 usernamePasswordLoginSize, usernamePasswordLogin);
527
0
    if(sc != UA_STATUSCODE_GOOD)
528
0
        return sc;
529
530
0
    context = (AccessControlContext *)config->accessControl.context;
531
0
    context->loginCallback = loginCallback;
532
0
    context->loginContext = loginContext;
533
534
0
    return UA_STATUSCODE_GOOD;
535
0
}
536