Coverage Report

Created: 2026-04-06 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/S2OPC/src/ClientServer/configuration/sopc_user.c
Line
Count
Source
1
/*
2
 * Licensed to Systerel under one or more contributor license
3
 * agreements. See the NOTICE file distributed with this work
4
 * for additional information regarding copyright ownership.
5
 * Systerel licenses this file to you under the Apache
6
 * License, Version 2.0 (the "License"); you may not use this
7
 * file except in compliance with the License. You may obtain
8
 * a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
20
#include "sopc_user.h"
21
#include "sopc_assert.h"
22
#include "sopc_key_manager.h"
23
#include "sopc_macros.h"
24
#include "sopc_mem_alloc.h"
25
26
typedef enum
27
{
28
    USER_LOCAL,
29
    USER_ANONYMOUS,
30
    USER_USERNAME,
31
    USER_CERTIFICATE
32
} user_type_t;
33
34
typedef struct user_certificate_t
35
{
36
    SOPC_String thumbprint;
37
    SOPC_ByteString der;
38
} user_certificate_t;
39
40
struct SOPC_User
41
{
42
    user_type_t type;
43
    union
44
    {
45
        /** The \p username is only valid for the \p USER_USERNAME type. */
46
        SOPC_String username;
47
        user_certificate_t certificate;
48
    } data;
49
};
50
51
static const SOPC_User user_local = {.type = USER_LOCAL};
52
static const SOPC_User user_anonymous = {.type = USER_ANONYMOUS};
53
54
const SOPC_User* SOPC_User_GetLocal(void)
55
0
{
56
0
    return &user_local;
57
0
}
58
59
bool SOPC_User_IsLocal(const SOPC_User* user)
60
0
{
61
0
    return &user_local == user;
62
0
}
63
64
const SOPC_User* SOPC_User_GetAnonymous(void)
65
0
{
66
0
    return &user_anonymous;
67
0
}
68
69
bool SOPC_User_IsAnonymous(const SOPC_User* user)
70
0
{
71
0
    return &user_anonymous == user;
72
0
}
73
74
SOPC_User* SOPC_User_CreateUsername(SOPC_String* username)
75
0
{
76
0
    SOPC_User* user = SOPC_Calloc(1, sizeof(SOPC_User));
77
0
    if (NULL == user)
78
0
    {
79
0
        return NULL;
80
0
    }
81
82
0
    user->type = USER_USERNAME;
83
0
    SOPC_String_Initialize(&user->data.username);
84
0
    SOPC_ReturnStatus status = SOPC_String_Copy(&user->data.username, username);
85
0
    if (SOPC_STATUS_OK != status)
86
0
    {
87
0
        SOPC_String_Clear(&user->data.username);
88
0
        SOPC_Free(user);
89
0
        user = NULL;
90
0
    }
91
92
0
    return user;
93
0
}
94
95
SOPC_User* SOPC_User_CreateCertificate(SOPC_ByteString* certificateData)
96
0
{
97
0
    SOPC_CertificateList* pCert = NULL;
98
0
    char* thumbprint = NULL;
99
0
    SOPC_User* user = SOPC_Calloc(1, sizeof(SOPC_User));
100
0
    if (NULL == user)
101
0
    {
102
0
        return NULL;
103
0
    }
104
105
0
    SOPC_ReturnStatus status = SOPC_KeyManager_Certificate_CreateOrAddFromDER(
106
0
        certificateData->Data, (uint32_t) certificateData->Length, &pCert);
107
0
    if (SOPC_STATUS_OK == status)
108
0
    {
109
0
        thumbprint = SOPC_KeyManager_Certificate_GetCstring_SHA1(pCert);
110
0
        if (NULL == thumbprint)
111
0
        {
112
0
            status = SOPC_STATUS_NOK;
113
0
        }
114
0
    }
115
116
0
    if (SOPC_STATUS_OK == status)
117
0
    {
118
0
        user->type = USER_CERTIFICATE;
119
0
        status = SOPC_String_InitializeFromCString(&user->data.certificate.thumbprint, thumbprint);
120
0
    }
121
122
0
    if (SOPC_STATUS_OK == status)
123
0
    {
124
0
        SOPC_ByteString_Initialize(&user->data.certificate.der);
125
0
        status = SOPC_ByteString_Copy(&user->data.certificate.der, certificateData);
126
0
    }
127
128
0
    if (SOPC_STATUS_OK != status)
129
0
    {
130
0
        SOPC_String_Clear(&user->data.certificate.thumbprint);
131
0
        SOPC_ByteString_Clear(&user->data.certificate.der);
132
0
        SOPC_Free(user);
133
0
        user = NULL;
134
0
    }
135
136
0
    SOPC_KeyManager_Certificate_Free(pCert);
137
0
    SOPC_Free(thumbprint);
138
0
    return user;
139
0
}
140
141
const SOPC_String* SOPC_User_GetUsername(const SOPC_User* user)
142
0
{
143
0
    if (SOPC_User_IsUsername(user))
144
0
    {
145
0
        return &user->data.username;
146
0
    }
147
0
    else
148
0
    {
149
0
        return NULL;
150
0
    }
151
0
}
152
153
bool SOPC_User_IsUsername(const SOPC_User* user)
154
0
{
155
0
    if (NULL != user)
156
0
    {
157
0
        return USER_USERNAME == user->type;
158
0
    }
159
0
    else
160
0
    {
161
0
        return false;
162
0
    }
163
0
}
164
165
const SOPC_ByteString* SOPC_User_GetCertificate(const SOPC_User* user)
166
0
{
167
0
    if (SOPC_User_IsCertificate(user))
168
0
    {
169
0
        return &user->data.certificate.der;
170
0
    }
171
0
    else
172
0
    {
173
0
        return NULL;
174
0
    }
175
0
}
176
177
const SOPC_String* SOPC_User_GetCertificate_Thumbprint(const SOPC_User* user)
178
0
{
179
0
    if (SOPC_User_IsCertificate(user))
180
0
    {
181
0
        return &user->data.certificate.thumbprint;
182
0
    }
183
0
    else
184
0
    {
185
0
        return NULL;
186
0
    }
187
0
}
188
189
bool SOPC_User_IsCertificate(const SOPC_User* user)
190
0
{
191
0
    if (NULL != user)
192
0
    {
193
0
        return USER_CERTIFICATE == user->type;
194
0
    }
195
0
    else
196
0
    {
197
0
        return false;
198
0
    }
199
0
}
200
201
bool SOPC_User_Equal(const SOPC_User* left, const SOPC_User* right)
202
0
{
203
0
    if (NULL == left || NULL == right)
204
0
    {
205
0
        return left == right;
206
0
    }
207
208
0
    bool sameCert = false;
209
210
0
    if (left->type == right->type)
211
0
    {
212
0
        switch (left->type)
213
0
        {
214
0
        case USER_LOCAL:
215
0
        case USER_ANONYMOUS:
216
0
            return true;
217
0
        case USER_USERNAME:
218
0
            return SOPC_String_Equal(&left->data.username, &right->data.username);
219
0
        case USER_CERTIFICATE:
220
0
            sameCert = SOPC_String_Equal(&left->data.certificate.thumbprint, &right->data.certificate.thumbprint);
221
0
            if (sameCert)
222
0
            {
223
0
                sameCert = SOPC_ByteString_Equal(&left->data.certificate.der, &right->data.certificate.der);
224
0
            }
225
0
            return sameCert;
226
0
        default:
227
0
            SOPC_ASSERT(false && "Unknown Type");
228
0
            break;
229
0
        }
230
0
    }
231
0
    return false;
232
0
}
233
234
void SOPC_User_Free(SOPC_User** ppUser)
235
0
{
236
0
    if (NULL == ppUser || NULL == *ppUser)
237
0
    {
238
0
        return;
239
0
    }
240
241
0
    SOPC_User* user = *ppUser;
242
0
    if (!SOPC_User_IsLocal(user) && !SOPC_User_IsAnonymous(user))
243
0
    {
244
0
        SOPC_Boolean is_username = SOPC_User_IsUsername(user);
245
0
        SOPC_Boolean is_certificate = SOPC_User_IsCertificate(user);
246
0
        SOPC_ASSERT(is_username || is_certificate);
247
0
        if (is_username)
248
0
        {
249
0
            SOPC_String_Clear(&user->data.username);
250
0
        }
251
0
        if (is_certificate)
252
0
        {
253
0
            SOPC_String_Clear(&user->data.certificate.thumbprint);
254
0
            SOPC_ByteString_Clear(&user->data.certificate.der);
255
0
        }
256
0
        SOPC_Free(user);
257
0
    }
258
0
    *ppUser = NULL;
259
0
}
260
261
SOPC_User* SOPC_User_Copy(const SOPC_User* user)
262
0
{
263
0
    SOPC_ReturnStatus status = SOPC_STATUS_NOK;
264
0
    SOPC_User* userCopy = NULL;
265
0
    if (NULL == user)
266
0
    {
267
0
        return NULL;
268
0
    }
269
0
    if (SOPC_User_IsLocal(user))
270
0
    {
271
0
        SOPC_GCC_DIAGNOSTIC_IGNORE_CAST_CONST
272
0
        userCopy = (SOPC_User*) SOPC_User_GetLocal();
273
0
        SOPC_GCC_DIAGNOSTIC_RESTORE
274
0
    }
275
0
    else if (SOPC_User_IsAnonymous(user))
276
0
    {
277
0
        SOPC_GCC_DIAGNOSTIC_IGNORE_CAST_CONST
278
0
        userCopy = (SOPC_User*) SOPC_User_GetAnonymous();
279
0
        SOPC_GCC_DIAGNOSTIC_RESTORE
280
0
    }
281
0
    else if (SOPC_User_IsUsername(user))
282
0
    {
283
0
        userCopy = SOPC_Calloc(1, sizeof(*userCopy));
284
0
        if (NULL != userCopy)
285
0
        {
286
0
            userCopy->type = user->type;
287
0
            status = SOPC_String_Copy(&userCopy->data.username, &user->data.username);
288
0
        }
289
0
        if (SOPC_STATUS_OK != status)
290
0
        {
291
0
            SOPC_Free(userCopy);
292
0
            userCopy = NULL;
293
0
        }
294
0
    }
295
0
    else
296
0
    {
297
0
        userCopy = SOPC_Calloc(1, sizeof(*userCopy));
298
0
        if (NULL != userCopy)
299
0
        {
300
0
            userCopy->type = user->type;
301
0
            status = SOPC_String_Copy(&userCopy->data.certificate.thumbprint, &user->data.certificate.thumbprint);
302
0
        }
303
0
        if (SOPC_STATUS_OK == status)
304
0
        {
305
0
            status = SOPC_ByteString_Copy(&userCopy->data.certificate.der, &user->data.certificate.der);
306
0
        }
307
0
        if (SOPC_STATUS_OK != status)
308
0
        {
309
0
            SOPC_String_Clear(&userCopy->data.certificate.thumbprint);
310
0
            SOPC_ByteString_Clear(&userCopy->data.certificate.der);
311
0
            SOPC_Free(userCopy);
312
0
            userCopy = NULL;
313
0
        }
314
0
    }
315
0
    return userCopy;
316
0
}
317
318
const char* SOPC_User_ToCString(const SOPC_User* user)
319
0
{
320
0
    if (NULL == user)
321
0
    {
322
0
        return "NULL";
323
0
    }
324
325
0
    switch (user->type)
326
0
    {
327
0
    case USER_LOCAL:
328
0
        return "[local_user]";
329
0
    case USER_ANONYMOUS:
330
0
        return "[anonymous]";
331
0
    case USER_USERNAME:
332
0
        return SOPC_String_GetRawCString(SOPC_User_GetUsername(user));
333
0
    case USER_CERTIFICATE:
334
0
        return SOPC_String_GetRawCString(SOPC_User_GetCertificate_Thumbprint(user));
335
0
    default:
336
0
        SOPC_ASSERT(false && "Unknown user type");
337
0
    }
338
339
0
    return NULL;
340
0
}