Coverage Report

Created: 2025-10-28 06:49

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
    SOPC_ASSERT(SOPC_User_IsUsername(user));
144
0
    return &user->data.username;
145
0
}
146
147
bool SOPC_User_IsUsername(const SOPC_User* user)
148
0
{
149
0
    SOPC_ASSERT(NULL != user);
150
0
    return USER_USERNAME == user->type;
151
0
}
152
153
const SOPC_ByteString* SOPC_User_GetCertificate(const SOPC_User* user)
154
0
{
155
0
    SOPC_ASSERT(SOPC_User_IsCertificate(user));
156
0
    return &user->data.certificate.der;
157
0
}
158
159
const SOPC_String* SOPC_User_GetCertificate_Thumbprint(const SOPC_User* user)
160
0
{
161
0
    SOPC_ASSERT(SOPC_User_IsCertificate(user));
162
0
    return &user->data.certificate.thumbprint;
163
0
}
164
165
bool SOPC_User_IsCertificate(const SOPC_User* user)
166
0
{
167
0
    SOPC_ASSERT(NULL != user);
168
0
    return USER_CERTIFICATE == user->type;
169
0
}
170
171
bool SOPC_User_Equal(const SOPC_User* left, const SOPC_User* right)
172
0
{
173
0
    SOPC_ASSERT(NULL != left);
174
0
    SOPC_ASSERT(NULL != right);
175
176
0
    bool sameCert = false;
177
178
0
    if (left->type == right->type)
179
0
    {
180
0
        switch (left->type)
181
0
        {
182
0
        case USER_LOCAL:
183
0
        case USER_ANONYMOUS:
184
0
            return true;
185
0
        case USER_USERNAME:
186
0
            return SOPC_String_Equal(&left->data.username, &right->data.username);
187
0
        case USER_CERTIFICATE:
188
0
            sameCert = SOPC_String_Equal(&left->data.certificate.thumbprint, &right->data.certificate.thumbprint);
189
0
            if (sameCert)
190
0
            {
191
0
                sameCert = SOPC_ByteString_Equal(&left->data.certificate.der, &right->data.certificate.der);
192
0
            }
193
0
            return sameCert;
194
0
        default:
195
0
            SOPC_ASSERT(false && "Unknown Type");
196
0
            break;
197
0
        }
198
0
    }
199
0
    return false;
200
0
}
201
202
void SOPC_User_Free(SOPC_User** ppUser)
203
0
{
204
0
    if (NULL == ppUser || NULL == *ppUser)
205
0
    {
206
0
        return;
207
0
    }
208
209
0
    SOPC_User* user = *ppUser;
210
0
    if (!SOPC_User_IsLocal(user) && !SOPC_User_IsAnonymous(user))
211
0
    {
212
0
        SOPC_Boolean is_username = SOPC_User_IsUsername(user);
213
0
        SOPC_Boolean is_certificate = SOPC_User_IsCertificate(user);
214
0
        SOPC_ASSERT(is_username || is_certificate);
215
0
        if (is_username)
216
0
        {
217
0
            SOPC_String_Clear(&user->data.username);
218
0
        }
219
0
        if (is_certificate)
220
0
        {
221
0
            SOPC_String_Clear(&user->data.certificate.thumbprint);
222
0
            SOPC_ByteString_Clear(&user->data.certificate.der);
223
0
        }
224
0
        SOPC_Free(user);
225
0
    }
226
0
    *ppUser = NULL;
227
0
}
228
229
SOPC_User* SOPC_User_Copy(const SOPC_User* user)
230
0
{
231
0
    SOPC_ReturnStatus status = SOPC_STATUS_NOK;
232
0
    SOPC_User* userCopy = NULL;
233
0
    if (NULL == user)
234
0
    {
235
0
        return NULL;
236
0
    }
237
0
    if (SOPC_User_IsLocal(user))
238
0
    {
239
0
        SOPC_GCC_DIAGNOSTIC_IGNORE_CAST_CONST
240
0
        userCopy = (SOPC_User*) SOPC_User_GetLocal();
241
0
        SOPC_GCC_DIAGNOSTIC_RESTORE
242
0
    }
243
0
    else if (SOPC_User_IsAnonymous(user))
244
0
    {
245
0
        SOPC_GCC_DIAGNOSTIC_IGNORE_CAST_CONST
246
0
        userCopy = (SOPC_User*) SOPC_User_GetAnonymous();
247
0
        SOPC_GCC_DIAGNOSTIC_RESTORE
248
0
    }
249
0
    else if (SOPC_User_IsUsername(user))
250
0
    {
251
0
        userCopy = SOPC_Calloc(1, sizeof(*userCopy));
252
0
        if (NULL != userCopy)
253
0
        {
254
0
            userCopy->type = user->type;
255
0
            status = SOPC_String_Copy(&userCopy->data.username, &user->data.username);
256
0
        }
257
0
        if (SOPC_STATUS_OK != status)
258
0
        {
259
0
            SOPC_Free(userCopy);
260
0
            userCopy = NULL;
261
0
        }
262
0
    }
263
0
    else
264
0
    {
265
0
        userCopy = SOPC_Calloc(1, sizeof(*userCopy));
266
0
        if (NULL != userCopy)
267
0
        {
268
0
            userCopy->type = user->type;
269
0
            status = SOPC_String_Copy(&userCopy->data.certificate.thumbprint, &user->data.certificate.thumbprint);
270
0
        }
271
0
        if (SOPC_STATUS_OK == status)
272
0
        {
273
0
            status = SOPC_ByteString_Copy(&userCopy->data.certificate.der, &user->data.certificate.der);
274
0
        }
275
0
        if (SOPC_STATUS_OK != status)
276
0
        {
277
0
            SOPC_String_Clear(&userCopy->data.certificate.thumbprint);
278
0
            SOPC_ByteString_Clear(&userCopy->data.certificate.der);
279
0
            SOPC_Free(userCopy);
280
0
            userCopy = NULL;
281
0
        }
282
0
    }
283
0
    return userCopy;
284
0
}
285
286
const char* SOPC_User_ToCString(const SOPC_User* user)
287
0
{
288
0
    if (NULL == user)
289
0
    {
290
0
        return "NULL";
291
0
    }
292
293
0
    switch (user->type)
294
0
    {
295
0
    case USER_LOCAL:
296
0
        return "[local_user]";
297
0
    case USER_ANONYMOUS:
298
0
        return "[anonymous]";
299
0
    case USER_USERNAME:
300
0
        return SOPC_String_GetRawCString(SOPC_User_GetUsername(user));
301
0
    case USER_CERTIFICATE:
302
0
        return SOPC_String_GetRawCString(SOPC_User_GetCertificate_Thumbprint(user));
303
0
    default:
304
0
        SOPC_ASSERT(false && "Unknown user type");
305
0
    }
306
307
0
    return NULL;
308
0
}