Coverage Report

Created: 2026-11-12 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/open62541_15/src/server/ua_server_utils.c
Line
Count
Source
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
 *
5
 *    Copyright 2016-2017 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
6
 *    Copyright 2016 (c) Lorenz Haas
7
 *    Copyright 2017 (c) frax2222
8
 *    Copyright 2017 (c) Florian Palm
9
 *    Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
10
 *    Copyright 2017 (c) Julian Grothoff
11
 */
12
13
#include "ua_server_internal.h"
14
15
/****************************/
16
/* Custom DataType Handling */
17
/****************************/
18
19
const UA_DataTypeArray *
20
3.18M
serverCustomTypes(UA_Server *server) {
21
3.18M
    if(server->customTypes_internalSize == 0)
22
3.18M
        return server->config.customDataTypes;
23
0
    server->customTypes_internal[server->customTypes_internalSize-1].next = server->config.customDataTypes;
24
0
    return server->customTypes_internal;
25
3.18M
}
26
27
const UA_DataTypeArray *
28
1.53M
UA_Server_getDataTypes(UA_Server *server) {
29
1.53M
    lockServer(server);
30
1.53M
    const UA_DataTypeArray * out = serverCustomTypes(server);
31
1.53M
    unlockServer(server);
32
1.53M
    return out;
33
1.53M
}
34
35
const UA_DataType *
36
1.60M
UA_Server_findDataType(UA_Server *server, const UA_NodeId *typeId) {
37
1.60M
    return UA_findDataTypeWithCustom(typeId, serverCustomTypes(server));
38
1.60M
}
39
40
/* DataTypes need a stable pointer. So we allocate an array of 64 datatypes.
41
 * When that is full we move the server->customTypes_internal into a
42
 * heap-structure that gets cleaned up with the server lifecycle. */
43
static UA_StatusCode
44
0
addDataType(UA_Server *server, UA_DataType *dt) {
45
    /* Allocate the space for the new DataType */
46
0
#define TYPES_LIST_SIZE 64
47
0
    UA_DataTypeArray *current = NULL;
48
0
    if(server->customTypes_internalSize > 0)
49
0
        current = &server->customTypes_internal[server->customTypes_internalSize-1];
50
0
    if(!current || current->typesSize == TYPES_LIST_SIZE) {
51
        /* Increase the list-of-lists size */
52
0
        UA_DataTypeArray *lol = (UA_DataTypeArray*)
53
0
            UA_realloc(server->customTypes_internal,
54
0
                       sizeof(UA_DataTypeArray) * (server->customTypes_internalSize+1));
55
0
        if(!lol)
56
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
57
0
        memset(&lol[server->customTypes_internalSize], 0, sizeof(UA_DataTypeArray));
58
0
        server->customTypes_internal = lol;
59
0
        server->customTypes_internalSize++;
60
61
        /* Update the next-pointers for the internal DataTypeArray */
62
0
        for(size_t i = 0; i < server->customTypes_internalSize-1; i++)
63
0
            lol[i].next = &lol[i+1];
64
65
        /* Add a new types list. With the space for the datatypes already appended */
66
0
        current = &server->customTypes_internal[server->customTypes_internalSize-1];
67
0
        current->types = (UA_DataType*)UA_calloc(TYPES_LIST_SIZE, sizeof(UA_DataType));
68
0
        current->typesSize = 0;
69
0
        if(!current->types) {
70
0
            server->customTypes_internalSize--;
71
0
            return UA_STATUSCODE_BADOUTOFMEMORY;
72
0
        }
73
0
    }
74
75
    /* Move the datatype into the stable location in the server. Repair
76
     * self-referential members because their source pointer is about to go
77
     * out of scope. */
78
0
    UA_DataType *target = &current->types[current->typesSize];
79
0
    *target = *dt;
80
0
    for(size_t i = 0; i < target->membersSize; i++) {
81
0
        if(target->members[i].memberType == dt)
82
0
            target->members[i].memberType = target;
83
0
    }
84
0
    current->typesSize++;
85
0
    return UA_STATUSCODE_GOOD;
86
0
}
87
88
UA_StatusCode
89
UA_Server_addDataType(UA_Server *server, const UA_NodeId parentNodeId,
90
0
                      const UA_DataType *type) {
91
    /* Check that the type does not already exist. We do not allow changes to
92
     * DataTypes once they are set. */
93
0
    if(UA_Server_findDataType(server, &type->typeId))
94
0
        return UA_STATUSCODE_BADNODEIDEXISTS;
95
96
    /* Make a copy of the UA_DataType */
97
0
    UA_DataType dt2;
98
0
    UA_StatusCode res = UA_DataType_copy(type, &dt2);
99
0
    if(res != UA_STATUSCODE_GOOD)
100
0
        return res;
101
102
    /* Add the UA_DataType to the server */
103
0
    res = addDataType(server, &dt2);
104
0
    if(res != UA_STATUSCODE_GOOD)
105
0
        UA_DataType_clear(&dt2);
106
0
    return res;
107
0
}
108
109
#ifdef UA_TYPES_STRUCTUREDESCRIPTION
110
/* Keep exact lookups distinct from resolving a simple subtype's storage.
111
 * In particular, an unregistered structure must never inherit its parent's
112
 * layout implicitly: it may introduce additional fields or encodings. */
113
static const UA_DataType *
114
0
resolveDataTypeRepresentation(UA_Server *server, const UA_NodeId *typeId) {
115
0
    lockServer(server);
116
0
    const UA_DataType *type = UA_Server_findDataType(server, typeId);
117
0
    if(type) {
118
0
        unlockServer(server);
119
0
        return type;
120
0
    }
121
122
0
    RefTree visited;
123
0
    if(RefTree_init(&visited) != UA_STATUSCODE_GOOD) {
124
0
        unlockServer(server);
125
0
        return NULL;
126
0
    }
127
128
0
    const UA_Node *node = UA_NODESTORE_GET_SELECTIVE(
129
0
        server, typeId, UA_NODEATTRIBUTESMASK_NONE,
130
0
        UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE),
131
0
        UA_BROWSEDIRECTION_INVERSE);
132
0
    while(node) {
133
0
        UA_Boolean duplicate = false;
134
0
        UA_StatusCode res = RefTree_addNodeId(&visited, &node->head.nodeId, &duplicate);
135
0
        if(res != UA_STATUSCODE_GOOD || duplicate ||
136
0
           node->head.nodeClass != UA_NODECLASS_DATATYPE) {
137
0
            UA_NODESTORE_RELEASE(server, node);
138
0
            break;
139
0
        }
140
141
0
        const UA_DataType *candidate =
142
0
            UA_Server_findDataType(server, &node->head.nodeId);
143
0
        if(candidate) {
144
0
            if(candidate->typeKind <= UA_DATATYPEKIND_DIAGNOSTICINFO &&
145
0
               candidate->typeKind != UA_DATATYPEKIND_EXTENSIONOBJECT)
146
0
                type = candidate;
147
0
            UA_NODESTORE_RELEASE(server, node);
148
0
            break;
149
0
        }
150
0
        const UA_Node *parent =
151
0
            getNodeType(server, &node->head, UA_NODEATTRIBUTESMASK_NODEID,
152
0
                        UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE),
153
0
                        UA_BROWSEDIRECTION_INVERSE);
154
0
        UA_NODESTORE_RELEASE(server, node);
155
0
        node = parent;
156
0
    }
157
0
    RefTree_clear(&visited);
158
0
    unlockServer(server);
159
0
    return type;
160
0
}
161
162
/* Replace an alias NodeId with the concrete datatype that defines its layout. */
163
static UA_StatusCode
164
0
normalizeDataTypeId(UA_Server *server, UA_NodeId *typeId) {
165
0
    if(UA_NodeId_isNull(typeId))
166
0
        return UA_STATUSCODE_GOOD;
167
0
    if(UA_Server_findDataType(server, typeId))
168
0
        return UA_STATUSCODE_GOOD;
169
0
    const UA_DataType *representation =
170
0
        resolveDataTypeRepresentation(server, typeId);
171
0
    if(!representation)
172
0
        return UA_STATUSCODE_BADNOTFOUND;
173
0
    UA_NodeId_clear(typeId);
174
0
    return UA_NodeId_copy(&representation->typeId, typeId);
175
0
}
176
177
#endif
178
179
UA_StatusCode
180
UA_Server_addDataTypeFromDescription(UA_Server *server,
181
0
                                     const UA_ExtensionObject *description) {
182
0
#ifdef UA_TYPES_STRUCTUREDESCRIPTION
183
    /* Normalize simple aliases in a temporary copy for memory-layout
184
     * construction. */
185
0
    UA_ExtensionObject layoutDescription;
186
0
    UA_StatusCode res = UA_ExtensionObject_copy(description, &layoutDescription);
187
0
    if(res != UA_STATUSCODE_GOOD)
188
0
        return res;
189
0
    if(UA_ExtensionObject_hasDecodedType(
190
0
           &layoutDescription, &UA_TYPES[UA_TYPES_STRUCTUREDESCRIPTION])) {
191
0
        UA_StructureDescription *structureDescription =
192
0
            (UA_StructureDescription*)layoutDescription.content.decoded.data;
193
0
        UA_StructureDefinition *definition =
194
0
            &structureDescription->structureDefinition;
195
0
        for(size_t i = 0; res == UA_STATUSCODE_GOOD &&
196
0
                        i < definition->fieldsSize; i++) {
197
0
            if(UA_NodeId_equal(&definition->fields[i].dataType,
198
0
                               &structureDescription->dataTypeId))
199
0
                continue;
200
0
            res = normalizeDataTypeId(server, &definition->fields[i].dataType);
201
0
        }
202
0
    }
203
0
    if(res != UA_STATUSCODE_GOOD) {
204
0
        UA_ExtensionObject_clear(&layoutDescription);
205
0
        return res;
206
0
    }
207
208
    /* Translate into a new UA_DataType */
209
0
    UA_DataType dt;
210
0
    res = UA_DataType_fromDescription(&dt, &layoutDescription,
211
0
                                      serverCustomTypes(server));
212
0
    UA_ExtensionObject_clear(&layoutDescription);
213
0
    if(res != UA_STATUSCODE_GOOD)
214
0
        return res;
215
216
#else
217
    /* Translate into a new UA_DataType */
218
    UA_DataType dt;
219
    UA_StatusCode res =
220
        UA_DataType_fromDescription(&dt, description, serverCustomTypes(server));
221
    if(res != UA_STATUSCODE_GOOD)
222
        return res;
223
224
#endif
225
226
    /* Check that the type does not already exist. We do not allow changes to
227
     * DataTypes once they are set. */
228
0
    if(UA_Server_findDataType(server, &dt.typeId)) {
229
0
        UA_DataType_clear(&dt);
230
0
        return UA_STATUSCODE_BADNODEIDEXISTS;
231
0
    }
232
233
    /* Add the UA_DataType to the server */
234
0
    res = addDataType(server, &dt);
235
0
    if(res != UA_STATUSCODE_GOOD)
236
0
        UA_DataType_clear(&dt);
237
0
    return res;
238
0
}
239
240
/********************************/
241
/* Information Model Operations */
242
/********************************/
243
244
struct ReturnTypeContext {
245
    UA_Server *server;
246
    UA_UInt32 attributeMask;
247
    UA_ReferenceTypeSet references;
248
    UA_BrowseDirection referenceDirections;
249
};
250
251
static void *
252
32.8M
returnFirstType(void *context, UA_ReferenceTarget *t) {
253
32.8M
    struct ReturnTypeContext *ctx = (struct ReturnTypeContext*)context;
254
    /* Don't release the node that is returned.
255
     * Continues to iterate if NULL is returned. */
256
32.8M
    return (void *)(uintptr_t)UA_NODESTORE_GETFROMREF_SELECTIVE(
257
32.8M
        ctx->server, t->targetId, ctx->attributeMask, ctx->references,
258
32.8M
        ctx->referenceDirections);
259
32.8M
}
260
261
const UA_Node *
262
getNodeType(UA_Server *server, const UA_NodeHead *head,
263
            UA_UInt32 attributeMask, UA_ReferenceTypeSet references,
264
32.9M
            UA_BrowseDirection referenceDirections) {
265
    /* The reference to the parent is different for variable and variabletype */
266
32.9M
    UA_Byte parentRefIndex;
267
32.9M
    UA_Boolean inverse;
268
32.9M
    switch(head->nodeClass) {
269
2.92M
    case UA_NODECLASS_OBJECT:
270
32.4M
    case UA_NODECLASS_VARIABLE:
271
32.4M
        parentRefIndex = UA_REFERENCETYPEINDEX_HASTYPEDEFINITION;
272
32.4M
        inverse = false;
273
32.4M
        break;
274
0
    case UA_NODECLASS_OBJECTTYPE:
275
491k
    case UA_NODECLASS_VARIABLETYPE:
276
491k
    case UA_NODECLASS_REFERENCETYPE:
277
491k
    case UA_NODECLASS_DATATYPE:
278
491k
        parentRefIndex = UA_REFERENCETYPEINDEX_HASSUBTYPE;
279
491k
        inverse = true;
280
491k
        break;
281
0
    default:
282
0
        return NULL;
283
32.9M
    }
284
285
32.9M
    struct ReturnTypeContext ctx;
286
32.9M
    ctx.server = server;
287
32.9M
    ctx.attributeMask = attributeMask;
288
32.9M
    ctx.references = references;
289
32.9M
    ctx.referenceDirections = referenceDirections;
290
291
    /* Return the first matching candidate */
292
67.3M
    for(size_t i = 0; i < head->referencesSize; ++i) {
293
67.1M
        UA_NodeReferenceKind *rk = &head->references[i];
294
67.1M
        if(rk->isInverse != inverse)
295
32.1M
            continue;
296
35.0M
        if(rk->referenceTypeIndex != parentRefIndex)
297
2.21M
            continue;
298
32.8M
        const UA_Node *type = (const UA_Node*)
299
32.8M
            UA_NodeReferenceKind_iterate(rk, returnFirstType, &ctx);
300
32.8M
        if(type)
301
32.8M
            return type;
302
32.8M
    }
303
304
135k
    return NULL;
305
32.9M
}
306
307
UA_Boolean
308
19.7k
UA_Node_hasSubTypeOrInstances(const UA_NodeHead *head) {
309
60.6k
    for(size_t i = 0; i < head->referencesSize; ++i) {
310
40.9k
        if(head->references[i].isInverse == false &&
311
23.6k
           head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASSUBTYPE)
312
67
            return true;
313
40.9k
        if(head->references[i].isInverse == true &&
314
17.3k
           head->references[i].referenceTypeIndex == UA_REFERENCETYPEINDEX_HASTYPEDEFINITION)
315
27
            return true;
316
40.9k
    }
317
19.6k
    return false;
318
19.7k
}
319
320
UA_StatusCode
321
getTypeAndInterfaceHierarchy(UA_Server *server, const UA_NodeId *leafNode,
322
                             UA_Boolean includeLeaf, UA_NodeId **typeHierarchy,
323
13.6M
                             size_t *typeHierarchySize) {
324
13.6M
    UA_ReferenceTypeSet hastype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASTYPEDEFINITION);
325
13.6M
    UA_ReferenceTypeSet hassubtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
326
13.6M
    UA_ReferenceTypeSet hasinterface = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
327
328
    /* Initialize the tree and add the leaf */
329
13.6M
    RefTree rt;
330
13.6M
    UA_StatusCode res = RefTree_init(&rt);
331
13.6M
    if(res != UA_STATUSCODE_GOOD)
332
0
        return res;
333
13.6M
    res = RefTree_addNodeId(&rt, leafNode, NULL);
334
13.6M
    if(res != UA_STATUSCODE_GOOD)
335
0
        goto errout;
336
337
    /* Get all types */
338
13.6M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hastype,
339
13.6M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
340
13.6M
    if(res != UA_STATUSCODE_GOOD)
341
0
        goto errout;
342
343
    /* Get all super types */
344
13.6M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_INVERSE, &hassubtype,
345
13.6M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
346
13.6M
    if(res != UA_STATUSCODE_GOOD)
347
0
        goto errout;
348
349
    /* Get all interfaces */
350
13.6M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hasinterface,
351
13.6M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
352
353
13.6M
 errout:
354
13.6M
    if(res != UA_STATUSCODE_GOOD || rt.size == 0) {
355
0
        RefTree_clear(&rt);
356
0
        return res;
357
0
    }
358
359
    /* Make the array of ExpandedNodeId into an array of NodeId */
360
13.6M
    UA_NodeId *outArray = (UA_NodeId*)rt.targets;
361
13.6M
    size_t pos = 0;
362
41.6M
    for(size_t i = 0; i < rt.size; i++) {
363
28.0M
        UA_NodeId *n = &outArray[pos];
364
28.0M
        UA_ExpandedNodeId *e = &rt.targets[i];
365
28.0M
        if(!UA_ExpandedNodeId_isLocal(e)) {
366
0
            UA_ExpandedNodeId_clear(e);
367
0
            continue;
368
0
        }
369
28.0M
        *n = e->nodeId;
370
28.0M
        UA_String_clear(&e->namespaceUri);
371
28.0M
        pos++;
372
28.0M
    }
373
374
13.6M
    *typeHierarchySize = pos;
375
13.6M
    *typeHierarchy = outArray;
376
13.6M
    return UA_STATUSCODE_GOOD;
377
13.6M
}
378
379
UA_StatusCode
380
getAllInterfaces(UA_Server *server, const UA_NodeId *objectNode,
381
1.42M
                 UA_NodeId **interfaceNodes, size_t *interfaceNodesSize) {
382
1.42M
    UA_ReferenceTypeSet hastype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASTYPEDEFINITION);
383
1.42M
    UA_ReferenceTypeSet hassubtype = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASSUBTYPE);
384
1.42M
    UA_ReferenceTypeSet hasinterface = UA_REFTYPESET(UA_REFERENCETYPEINDEX_HASINTERFACE);
385
386
    /* Initialize the tree and add the leaf */
387
1.42M
    size_t beforeInterfaces = 0;
388
1.42M
    RefTree rt;
389
1.42M
    UA_StatusCode res = RefTree_init(&rt);
390
1.42M
    if(res != UA_STATUSCODE_GOOD)
391
0
        return res;
392
1.42M
    res = RefTree_addNodeId(&rt, objectNode, NULL);
393
1.42M
    if(res != UA_STATUSCODE_GOOD)
394
0
        goto errout;
395
396
    /* Get all types */
397
1.42M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hastype,
398
1.42M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
399
1.42M
    if(res != UA_STATUSCODE_GOOD)
400
0
        goto errout;
401
402
    /* Get all super types */
403
1.42M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_INVERSE, &hassubtype,
404
1.42M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
405
1.42M
    if(res != UA_STATUSCODE_GOOD)
406
0
        goto errout;
407
408
    /* Get all interfaces */
409
1.42M
    beforeInterfaces = rt.size; /* Return only the interfaces */
410
1.42M
    res = browseRecursiveRefTree(server, &rt, UA_BROWSEDIRECTION_FORWARD, &hasinterface,
411
1.42M
                                 UA_NODECLASS_OBJECTTYPE | UA_NODECLASS_VARIABLETYPE);
412
413
1.42M
 errout:
414
1.42M
    if(res != UA_STATUSCODE_GOOD || rt.size == 0) {
415
0
        RefTree_clear(&rt);
416
0
        return res;
417
0
    }
418
419
    /* Make the array of ExpandedNodeId into an array of NodeId */
420
1.42M
    UA_NodeId *outArray = (UA_NodeId*)rt.targets;
421
1.42M
    size_t pos = 0;
422
5.84M
    for(size_t i = 0; i < rt.size; i++) {
423
4.41M
        UA_NodeId *n = &outArray[pos];
424
4.41M
        UA_ExpandedNodeId *e = &rt.targets[i];
425
4.41M
        if(i < beforeInterfaces || !UA_ExpandedNodeId_isLocal(e)) {
426
4.41M
            UA_ExpandedNodeId_clear(e);
427
4.41M
            continue;
428
4.41M
        }
429
0
        *n = e->nodeId;
430
0
        UA_String_clear(&e->namespaceUri);
431
0
        pos++;
432
0
    }
433
434
    /* No interfaces found */
435
1.42M
    if(pos == 0) {
436
1.42M
        RefTree_clear(&rt);
437
1.42M
        outArray = NULL;
438
1.42M
    }
439
440
1.42M
    *interfaceNodesSize = pos;
441
1.42M
    *interfaceNodes = outArray;
442
1.42M
    return UA_STATUSCODE_GOOD;
443
1.42M
}
444
445
/* Get the node, make the changes and release */
446
UA_StatusCode
447
editNode(UA_Server *server, UA_Session *session, const UA_NodeId *nodeId,
448
         UA_UInt32 attributeMask, UA_ReferenceTypeSet references,
449
         UA_BrowseDirection referenceDirections,
450
23.3M
         UA_EditNodeCallback callback, void *data) {
451
23.3M
    UA_Node *node =
452
23.3M
        UA_NODESTORE_GET_EDIT_SELECTIVE(server, nodeId, attributeMask,
453
23.3M
                                        references, referenceDirections);
454
23.3M
    if(!node)
455
19.8k
        return UA_STATUSCODE_BADNODEIDUNKNOWN;
456
23.2M
    UA_StatusCode retval = callback(server, session, node, data);
457
23.2M
    UA_NODESTORE_RELEASE(server, node);
458
23.2M
    return retval;
459
23.3M
}
460
461
/**************************/
462
/* Certificate Validation */
463
/**************************/
464
465
UA_StatusCode
466
validateCertificate(UA_Server *server, UA_CertificateGroup *cg,
467
                    const UA_SecurityPolicy *securityPolicy,
468
                    UA_SecureChannel *channel, UA_Session *session,
469
                    const char *logPrefix,
470
                    const UA_ApplicationDescription *ad,
471
0
                    const UA_ByteString certificate) {
472
    /* Verify the ApplicationUri */
473
0
    UA_StatusCode res = UA_STATUSCODE_GOOD;
474
0
    if(ad) {
475
0
        res = UA_CertificateUtils_verifyApplicationUri(&certificate,
476
0
                                                       &ad->applicationUri);
477
0
        if(res != UA_STATUSCODE_GOOD) {
478
0
            if(server->config.allowAllCertificateUris <= UA_RULEHANDLING_WARN) {
479
0
                if(session) {
480
0
                    UA_LOG_ERROR_SESSION(server->config.logging, session,
481
0
                                         "%s: The client's ApplicationUri "
482
0
                                         "could not be verified against the "
483
0
                                         "ApplicationUri %S from the client's "
484
0
                                         "ApplicationDescription", logPrefix,
485
0
                                         ad->applicationUri);
486
0
                } else if(channel) {
487
0
                    UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
488
0
                                         "%s: The client certificate's ApplicationUri "
489
0
                                         "could not be verified against the "
490
0
                                         "ApplicationUri %S from the client's "
491
0
                                         "ApplicationDescription", logPrefix,
492
0
                                         ad->applicationUri);
493
0
                } else {
494
0
                    UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
495
0
                                 "%s: The server certificate's ApplicationUri "
496
0
                                 "could not be verified against the "
497
0
                                 "ApplicationUri %S from its "
498
0
                                 "ApplicationDescription", logPrefix,
499
0
                                 ad->applicationUri);
500
0
                }
501
0
            }
502
0
            if(server->config.allowAllCertificateUris <= UA_RULEHANDLING_ABORT) {
503
0
                if(res == UA_STATUSCODE_BADCERTIFICATEURIINVALID) {
504
0
                    return UA_STATUSCODE_BADCERTIFICATEURIINVALID;
505
0
                } else {
506
0
                    return UA_STATUSCODE_BADCERTIFICATEINVALID;
507
0
                }
508
0
            }
509
0
        }
510
0
    }
511
512
    /* The server receives client application and user certificates. RSA
513
     * application certificates require clientAuth. For ECC application and user
514
     * certificates the extension is optional, but restrictive values apply. */
515
0
    if(securityPolicy && securityPolicy->policyType != UA_SECURITYPOLICYTYPE_NONE) {
516
0
        UA_Boolean applicationCertificate =
517
0
            (cg == &server->config.secureChannelPKI);
518
0
        UA_Boolean ekuRequired = applicationCertificate &&
519
0
            securityPolicy->policyType == UA_SECURITYPOLICYTYPE_RSA;
520
0
        res = UA_CertificateUtils_checkExtendedKeyUsage(
521
0
            &certificate, UA_CERTIFICATEEKU_CLIENTAUTH, ekuRequired);
522
0
        if(res == UA_STATUSCODE_BADCERTIFICATEUSENOTALLOWED) {
523
0
            if(server->config.certificateEkuRule <= UA_RULEHANDLING_WARN) {
524
0
                UA_LOG_WARNING(server->config.logging, UA_LOGCATEGORY_SECURITYPOLICY,
525
0
                               "%s: The client certificate does not permit clientAuth",
526
0
                               logPrefix);
527
0
            }
528
0
            if(server->config.certificateEkuRule == UA_RULEHANDLING_ABORT)
529
0
                return res;
530
0
        } else if(res != UA_STATUSCODE_GOOD) {
531
0
            return res;
532
0
        }
533
0
    }
534
535
0
    if(!cg->verifyCertificate) {
536
0
        UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
537
0
                     "%s: Could not validate the certificate "
538
0
                     "as the CertificateGroup is not configured", logPrefix);
539
0
        return UA_STATUSCODE_BADINTERNALERROR;
540
0
    }
541
542
    /* Validate in the CertificateGroup */
543
0
    res = cg->verifyCertificate(cg, &certificate);
544
0
    if(res != UA_STATUSCODE_GOOD) {
545
0
        const char *descr = UA_StatusCode_name(res);
546
0
        if(session) {
547
0
            UA_LOG_ERROR_SESSION(server->config.logging, session,
548
0
                                 "%s: The client certificate failed the verification "
549
0
                                 "in the CertificateGroup with StatusCode %s",
550
0
                                 logPrefix, descr);
551
0
        } else if(channel) {
552
0
            UA_LOG_ERROR_CHANNEL(server->config.logging, channel,
553
0
                                 "%s: The client certificate failed the verification "
554
0
                                 "in the CertificateGroup with StatusCode %s",
555
0
                                 logPrefix, descr);
556
0
        } else {
557
0
            UA_LOG_ERROR(server->config.logging, UA_LOGCATEGORY_SERVER,
558
0
                         "%s: The client certificate failed the verification "
559
0
                         "in the CertificateGroup with StatusCode %s",
560
0
                         logPrefix, descr);
561
0
        }
562
0
    }
563
0
    return res;
564
0
}
565
566
/*********************************/
567
/* Default attribute definitions */
568
/*********************************/
569
570
const UA_ObjectAttributes UA_ObjectAttributes_default = {
571
    0,                      /* specifiedAttributes */
572
    {{0, NULL}, {0, NULL}}, /* displayName */
573
    {{0, NULL}, {0, NULL}}, /* description */
574
    0, 0,                   /* writeMask (userWriteMask) */
575
    0                       /* eventNotifier */
576
};
577
578
const UA_VariableAttributes UA_VariableAttributes_default = {
579
    0,                           /* specifiedAttributes */
580
    {{0, NULL}, {0, NULL}},      /* displayName */
581
    {{0, NULL}, {0, NULL}},      /* description */
582
    0, 0,                        /* writeMask (userWriteMask) */
583
    {NULL, UA_VARIANT_DATA,
584
     0, NULL, 0, NULL},          /* value */
585
    {0, UA_NODEIDTYPE_NUMERIC,
586
     {UA_NS0ID_BASEDATATYPE}},   /* dataType */
587
    UA_VALUERANK_ANY,            /* valueRank */
588
    0, NULL,                     /* arrayDimensions */
589
    UA_ACCESSLEVELMASK_READ |    /* accessLevel */
590
    UA_ACCESSLEVELMASK_STATUSWRITE |
591
    UA_ACCESSLEVELMASK_TIMESTAMPWRITE,
592
    0,                           /* userAccessLevel */
593
    0.0,                         /* minimumSamplingInterval */
594
    false                        /* historizing */
595
};
596
597
const UA_MethodAttributes UA_MethodAttributes_default = {
598
    0,                      /* specifiedAttributes */
599
    {{0, NULL}, {0, NULL}}, /* displayName */
600
    {{0, NULL}, {0, NULL}}, /* description */
601
    0, 0,                   /* writeMask (userWriteMask) */
602
    true, true              /* executable (userExecutable) */
603
};
604
605
const UA_ObjectTypeAttributes UA_ObjectTypeAttributes_default = {
606
    0,                      /* specifiedAttributes */
607
    {{0, NULL}, {0, NULL}}, /* displayName */
608
    {{0, NULL}, {0, NULL}}, /* description */
609
    0, 0,                   /* writeMask (userWriteMask) */
610
    false                   /* isAbstract */
611
};
612
613
const UA_VariableTypeAttributes UA_VariableTypeAttributes_default = {
614
    0,                           /* specifiedAttributes */
615
    {{0, NULL}, {0, NULL}},      /* displayName */
616
    {{0, NULL}, {0, NULL}},      /* description */
617
    0, 0,                        /* writeMask (userWriteMask) */
618
    {NULL, UA_VARIANT_DATA,
619
     0, NULL, 0, NULL},          /* value */
620
    {0, UA_NODEIDTYPE_NUMERIC,
621
     {UA_NS0ID_BASEDATATYPE}},   /* dataType */
622
    UA_VALUERANK_ANY,            /* valueRank */
623
    0, NULL,                     /* arrayDimensions */
624
    false                        /* isAbstract */
625
};
626
627
const UA_ReferenceTypeAttributes UA_ReferenceTypeAttributes_default = {
628
    0,                      /* specifiedAttributes */
629
    {{0, NULL}, {0, NULL}}, /* displayName */
630
    {{0, NULL}, {0, NULL}}, /* description */
631
    0, 0,                   /* writeMask (userWriteMask) */
632
    false,                  /* isAbstract */
633
    false,                  /* symmetric */
634
    {{0, NULL}, {0, NULL}}  /* inverseName */
635
};
636
637
const UA_DataTypeAttributes UA_DataTypeAttributes_default = {
638
    0,                      /* specifiedAttributes */
639
    {{0, NULL}, {0, NULL}}, /* displayName */
640
    {{0, NULL}, {0, NULL}}, /* description */
641
    0, 0,                   /* writeMask (userWriteMask) */
642
    false                   /* isAbstract */
643
};
644
645
const UA_ViewAttributes UA_ViewAttributes_default = {
646
    0,                      /* specifiedAttributes */
647
    {{0, NULL}, {0, NULL}}, /* displayName */
648
    {{0, NULL}, {0, NULL}}, /* description */
649
    0, 0,                   /* writeMask (userWriteMask) */
650
    false,                  /* containsNoLoops */
651
    0                       /* eventNotifier */
652
};