Coverage Report

Created: 2026-11-12 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/src/conf.c
Line
Count
Source
1
/* conf.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
23
24
#if !defined(WOLFSSL_CONF_INCLUDED)
25
    #ifndef WOLFSSL_IGNORE_FILE_WARN
26
        #warning conf.c does not need to be compiled separately from ssl.c
27
    #endif
28
#else
29
30
/*******************************************************************************
31
 * START OF TXT_DB API
32
 ******************************************************************************/
33
34
0
#define LINE_BUFFER_SIZE 512 /* enough for a single row */
35
36
#if defined(OPENSSL_ALL) && !defined(NO_BIO)
37
/**
38
 * This function reads a tab delimetered CSV input and returns
39
 * a populated WOLFSSL_TXT_DB structure.
40
 * @param in Tab delimetered CSV input
41
 * @param num Number of fields in each row.
42
 * @return
43
 */
44
WOLFSSL_TXT_DB *wolfSSL_TXT_DB_read(WOLFSSL_BIO *in, int num)
45
0
{
46
0
    WOLFSSL_TXT_DB *ret = NULL;
47
0
    char *buf = NULL;
48
0
    char *bufEnd = NULL;
49
0
    char *idx = NULL;
50
0
    char* lineEnd = NULL;
51
0
    int bufSz;
52
0
    int failed = 1;
53
    /* Space in front of str reserved for field pointers + \0 */
54
0
    int fieldsSz = (num + 1) * sizeof(char *);
55
0
    WOLFSSL_ENTER("wolfSSL_TXT_DB_read");
56
57
0
    if (!in || num <= 0 || num > WOLFSSL_TXT_DB_MAX_FIELDS) {
58
0
        WOLFSSL_MSG("Bad parameter or too many fields");
59
0
        return NULL;
60
0
    }
61
62
0
    if (!(ret = (WOLFSSL_TXT_DB*)XMALLOC(sizeof(WOLFSSL_TXT_DB), NULL,
63
0
            DYNAMIC_TYPE_OPENSSL))) {
64
0
        WOLFSSL_MSG("malloc error");
65
0
        goto error;
66
0
    }
67
0
    XMEMSET (ret, 0, sizeof(WOLFSSL_TXT_DB));
68
0
    ret->num_fields = num;
69
70
0
    if (!(ret->data = wolfSSL_sk_WOLFSSL_STRING_new())) {
71
0
        WOLFSSL_MSG("wolfSSL_sk_WOLFSSL_STRING_new error");
72
0
        goto error;
73
0
    }
74
75
0
    bufSz = wolfSSL_BIO_get_len(in);
76
0
    if (bufSz <= 0 ||
77
0
            !(buf = (char*)XMALLOC(bufSz+1, NULL,
78
0
                    DYNAMIC_TYPE_TMP_BUFFER))) {
79
0
        WOLFSSL_MSG("malloc error or no data in BIO");
80
0
        goto error;
81
0
    }
82
83
0
    if (wolfSSL_BIO_read(in, buf, bufSz) != bufSz) {
84
0
        WOLFSSL_MSG("malloc error or no data in BIO");
85
0
        goto error;
86
0
    }
87
88
0
    buf[bufSz] = '\0';
89
0
    idx = buf;
90
0
    for (bufEnd = buf + bufSz; idx < bufEnd; idx = lineEnd + 1) {
91
0
        char* strBuf = NULL;
92
0
        char** fieldPtr = NULL;
93
0
        int fieldPtrIdx = 0;
94
0
        char* fieldCheckIdx = NULL;
95
0
        lineEnd = XSTRNSTR(idx, "\n", (size_t)(bufEnd - idx));
96
0
        if (!lineEnd)
97
0
            lineEnd = bufEnd;
98
0
        if (idx == lineEnd) /* empty line */
99
0
            continue;
100
0
        if (*idx == '#')
101
0
            continue;
102
0
        *lineEnd = '\0';
103
0
        strBuf = (char*)XMALLOC(fieldsSz + (lineEnd - idx) + 1, NULL,
104
0
                                DYNAMIC_TYPE_OPENSSL);
105
0
        if (!strBuf) {
106
0
            WOLFSSL_MSG("malloc error");
107
0
            goto error;
108
0
        }
109
0
        XMEMCPY(strBuf + fieldsSz, idx, lineEnd - idx + 1); /* + 1 for NULL */
110
0
        XMEMSET(strBuf, 0, fieldsSz);
111
        /* Check for appropriate number of fields */
112
0
        fieldPtr = (char**)strBuf;
113
0
        fieldCheckIdx = strBuf + fieldsSz;
114
0
        fieldPtr[fieldPtrIdx++] = fieldCheckIdx;
115
0
        while (*fieldCheckIdx != '\0') {
116
            /* Handle escaped tabs */
117
0
            if (*fieldCheckIdx == '\t' && fieldCheckIdx[-1] != '\\') {
118
0
                fieldPtr[fieldPtrIdx++] = fieldCheckIdx + 1;
119
0
                *fieldCheckIdx = '\0';
120
0
                if (fieldPtrIdx > num) {
121
0
                    WOLFSSL_MSG("too many fields");
122
0
                    XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
123
0
                    goto error;
124
0
                }
125
0
            }
126
0
            fieldCheckIdx++;
127
0
        }
128
0
        if (fieldPtrIdx != num) {
129
0
            WOLFSSL_MSG("wrong number of fields");
130
0
            XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
131
0
            goto error;
132
0
        }
133
0
        if (wolfSSL_sk_push(ret->data, strBuf) <= 0) {
134
0
            WOLFSSL_MSG("wolfSSL_sk_push error");
135
0
            XFREE(strBuf, NULL, DYNAMIC_TYPE_OPENSSL);
136
0
            goto error;
137
0
        }
138
0
    }
139
140
0
    failed = 0;
141
0
error:
142
0
    if (failed && ret) {
143
0
        wolfSSL_TXT_DB_free(ret);
144
0
        ret = NULL;
145
0
    }
146
0
    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
147
0
    return ret;
148
0
}
149
150
long wolfSSL_TXT_DB_write(WOLFSSL_BIO *out, WOLFSSL_TXT_DB *db)
151
0
{
152
0
    const WOLF_STACK_OF(WOLFSSL_STRING)* data;
153
0
    long totalLen = 0;
154
0
    WC_DECLARE_VAR(buf, char, LINE_BUFFER_SIZE, NULL); /* enough for a single row */
155
0
    char* bufEnd;
156
0
    int i;
157
158
0
    WOLFSSL_ENTER("wolfSSL_TXT_DB_write");
159
160
0
    if (!out || !db || !db->num_fields) {
161
0
        WOLFSSL_MSG("Bad parameter");
162
0
        return WOLFSSL_FAILURE;
163
0
    }
164
165
0
    WC_ALLOC_VAR_EX(buf, char, LINE_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER,
166
0
                    return WOLFSSL_FAILURE);
167
0
    bufEnd = buf + LINE_BUFFER_SIZE;
168
169
0
    data = db->data;
170
0
    while (data) {
171
0
        char** fields = (char**)data->data.string;
172
0
        char* idx = buf;
173
0
        int sz;
174
175
0
        if (!fields) {
176
0
            WOLFSSL_MSG("Missing row");
177
0
            WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
178
0
            return WOLFSSL_FAILURE;
179
0
        }
180
181
0
        for (i = 0; i < db->num_fields; i++) {
182
0
            const char* fieldValue = fields[i];
183
0
            if (!fieldValue) {
184
0
                fieldValue = "";
185
0
            }
186
187
            /* Copy over field escaping tabs */
188
0
            while (*fieldValue != '\0') {
189
0
                if (idx+1 < bufEnd) {
190
0
                    if (*fieldValue == '\t')
191
0
                        *idx++ = '\\';
192
0
                    *idx++ = *fieldValue++;
193
0
                }
194
0
                else {
195
0
                    WOLFSSL_MSG("Data row is too big");
196
0
                    WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
197
0
                    return WOLFSSL_FAILURE;
198
0
                }
199
0
            }
200
0
            if (idx < bufEnd) {
201
0
                *idx++ = '\t';
202
0
            }
203
0
            else {
204
0
                WOLFSSL_MSG("Data row is too big");
205
0
                WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
206
0
                return WOLFSSL_FAILURE;
207
0
            }
208
0
        }
209
0
        if (idx > buf)
210
0
            idx[-1] = '\n';
211
0
        else {
212
0
            WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
213
0
            return WOLFSSL_FAILURE;
214
0
        }
215
0
        sz = (int)(idx - buf);
216
217
0
        if (wolfSSL_BIO_write(out, buf, sz) != sz) {
218
0
            WOLFSSL_MSG("wolfSSL_BIO_write error");
219
0
            WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
220
0
            return WOLFSSL_FAILURE;
221
0
        }
222
0
        totalLen += sz;
223
224
0
        data = data->next;
225
0
    }
226
227
0
    WC_FREE_VAR_EX(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
228
0
    return totalLen;
229
0
}
230
231
int wolfSSL_TXT_DB_insert(WOLFSSL_TXT_DB *db, WOLFSSL_STRING *row)
232
0
{
233
0
    WOLFSSL_ENTER("wolfSSL_TXT_DB_insert");
234
235
0
    if (!db || !row || !db->data) {
236
0
        WOLFSSL_MSG("Bad parameter");
237
0
        return WOLFSSL_FAILURE;
238
0
    }
239
240
0
    if (wolfSSL_sk_push(db->data, row) <= 0) {
241
0
        WOLFSSL_MSG("wolfSSL_sk_push error");
242
0
        return WOLFSSL_FAILURE;
243
0
    }
244
245
0
    return WOLFSSL_SUCCESS;
246
0
}
247
248
void wolfSSL_TXT_DB_free(WOLFSSL_TXT_DB *db)
249
0
{
250
0
    WOLFSSL_ENTER("wolfSSL_TXT_DB_free");
251
0
    if (db) {
252
0
        if (db->data) {
253
0
            wolfSSL_sk_pop_free(db->data, NULL);
254
0
        }
255
0
        XFREE(db, NULL, DYNAMIC_TYPE_OPENSSL);
256
0
    }
257
0
}
258
259
int wolfSSL_TXT_DB_create_index(WOLFSSL_TXT_DB *db, int field,
260
        void* qual, wolf_sk_hash_cb hash, wolf_lh_compare_cb cmp)
261
0
{
262
0
    WOLFSSL_ENTER("wolfSSL_TXT_DB_create_index");
263
0
    (void)qual;
264
265
0
    if (!db || !hash || !cmp || field >= db->num_fields || field < 0) {
266
0
        WOLFSSL_MSG("Bad parameter");
267
0
        return WOLFSSL_FAILURE;
268
0
    }
269
270
0
    db->hash_fn[field] = hash;
271
0
    db->cmp_fn[field] = cmp;
272
273
0
    return WOLFSSL_SUCCESS;
274
0
}
275
276
WOLFSSL_STRING *wolfSSL_TXT_DB_get_by_index(WOLFSSL_TXT_DB *db, int idx,
277
        WOLFSSL_STRING *value)
278
0
{
279
0
    WOLF_STACK_OF(WOLFSSL_STRING)* data;
280
0
    WOLFSSL_STRING* row = NULL;
281
0
    unsigned long hash;
282
283
0
    WOLFSSL_ENTER("wolfSSL_TXT_DB_get_by_index");
284
285
0
    if (!db || !db->data || !value || idx < 0 || idx >= db->num_fields) {
286
0
        WOLFSSL_MSG("Bad parameter");
287
0
        return NULL;
288
0
    }
289
290
0
    if (!db->hash_fn[idx] || !db->cmp_fn[idx]) {
291
0
        WOLFSSL_MSG("Missing hash or compare functions");
292
0
        return NULL;
293
0
    }
294
295
    /* If first data struct has correct hash function
296
     * then assume others do too */
297
0
    if (db->data->hash_fn != db->hash_fn[idx]) {
298
        /* Set the hash and comp functions */
299
0
        data = db->data;
300
0
        while (data) {
301
0
            if (data->hash_fn != db->hash_fn[idx]) {
302
0
                data->hash_fn = db->hash_fn[idx];
303
0
                data->hash = 0;
304
0
            }
305
0
            data= data->next;
306
0
        }
307
0
    }
308
309
0
    hash = db->hash_fn[idx](value);
310
0
    for (data = db->data; data != NULL; data = data->next) {
311
0
        row = (WOLFSSL_STRING*)wolfssl_sk_node_get_data(data, 0);
312
0
        if (row != NULL) {
313
0
            if (data->hash == 0) {
314
0
                data->hash = db->hash_fn[idx](row);
315
0
            }
316
0
            if ((data->hash == hash) && (db->cmp_fn[idx](row, value) == 0)) {
317
0
                break;
318
0
            }
319
0
        }
320
0
        row = NULL;
321
0
    }
322
323
0
    return row;
324
0
}
325
326
#endif /* OPENSSL_ALL && !NO_BIO */
327
328
/*******************************************************************************
329
 * END OF TXT_DB API
330
 ******************************************************************************/
331
332
/*******************************************************************************
333
 * START OF CONF API
334
 ******************************************************************************/
335
336
#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \
337
 || defined(HAVE_STUNNEL)
338
#ifndef NO_WOLFSSL_STUB
339
void wolfSSL_OPENSSL_config(char *config_name)
340
0
{
341
0
    (void)config_name;
342
0
    WOLFSSL_STUB("OPENSSL_config");
343
0
}
344
#endif /* !NO_WOLFSSL_STUB */
345
#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_STUNNEL*/
346
347
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) && defined(OPENSSL_ALL)
348
349
/**
350
 * This is the same hashing algo for WOLFSSL_CONF_VALUE as OpenSSL
351
 */
352
static unsigned long wolfSSL_CONF_VALUE_hash(const WOLFSSL_CONF_VALUE *val)
353
0
{
354
0
    if (val)
355
0
        return (wolfSSL_LH_strhash(val->section) << 2) ^
356
0
                wolfSSL_LH_strhash(val->name);
357
0
    else
358
0
        return 0;
359
0
}
360
361
/* Use SHA[256] for hashing as OpenSSL uses a hash algorithm that is
362
 * "not as good as MD5, but still good" so using SHA should be more
363
 * than good enough for this application. The produced hashes don't
364
 * need to line up between OpenSSL and wolfSSL. The hashes are for
365
 * internal indexing only */
366
unsigned long wolfSSL_LH_strhash(const char *str)
367
0
{
368
0
    unsigned long ret = 0;
369
0
    int strLen;
370
0
#if !defined(NO_SHA)
371
0
    wc_Sha sha;
372
0
    byte digest[WC_SHA_DIGEST_SIZE];
373
#elif !defined(NO_SHA256)
374
    wc_Sha256 sha;
375
    byte digest[WC_SHA256_DIGEST_SIZE];
376
#endif
377
0
    WOLFSSL_ENTER("wolfSSL_LH_strhash");
378
379
0
    if (!str)
380
0
        return 0;
381
0
    strLen = (int)XSTRLEN(str);
382
383
0
#if !defined(NO_SHA)
384
0
    if (wc_InitSha_ex(&sha, NULL, 0) != 0) {
385
0
        WOLFSSL_MSG("SHA1 Init failed");
386
0
        return 0;
387
0
    }
388
389
0
    ret = wc_ShaUpdate(&sha, (const byte *)str, (word32)strLen);
390
0
    if (ret != 0) {
391
0
        WOLFSSL_MSG("SHA1 Update failed");
392
0
    } else {
393
0
        ret = wc_ShaFinal(&sha, digest);
394
0
        if (ret != 0) {
395
0
            WOLFSSL_MSG("SHA1 Final failed");
396
0
        }
397
0
    }
398
0
    wc_ShaFree(&sha);
399
#elif !defined(NO_SHA256)
400
    if (wc_InitSha256_ex(&sha, NULL, 0) != 0) {
401
        WOLFSSL_MSG("SHA256 Init failed");
402
        return 0;
403
    }
404
405
    ret = wc_Sha256Update(&sha, (const byte *)str, (word32)strLen);
406
    if (ret != 0) {
407
        WOLFSSL_MSG("SHA256 Update failed");
408
    } else {
409
        ret = wc_Sha256Final(&sha, digest);
410
        if (ret != 0) {
411
            WOLFSSL_MSG("SHA256 Final failed");
412
        }
413
    }
414
    wc_Sha256Free(&sha);
415
#endif
416
417
0
#if !defined(NO_SHA) || !defined(NO_SHA256)
418
0
    if (ret != 0)
419
0
        return 0;
420
421
    /* Take first 4 bytes in small endian as unsigned long */
422
0
    ret  =  (unsigned int)digest[0];
423
0
    ret |= ((unsigned int)digest[1] << 8 );
424
0
    ret |= ((unsigned int)digest[2] << 16);
425
0
    ret |= ((unsigned int)digest[3] << 24);
426
#else
427
    WOLFSSL_MSG("No SHA available for wolfSSL_LH_strhash");
428
#endif
429
0
    return ret;
430
0
}
431
432
WOLFSSL_CONF_VALUE *wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(
433
        WOLF_LHASH_OF(WOLFSSL_CONF_VALUE) *sk, WOLFSSL_CONF_VALUE *data)
434
0
{
435
0
    WOLFSSL_ENTER("wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve");
436
437
0
    if (!sk || !data) {
438
0
        WOLFSSL_MSG("Bad parameter");
439
0
        return NULL;
440
0
    }
441
442
0
    return (WOLFSSL_CONF_VALUE*)wolfSSL_lh_retrieve(sk, data);
443
0
}
444
445
int wolfSSL_CONF_modules_load(const WOLFSSL_CONF *cnf, const char *appname,
446
                      unsigned long flags)
447
0
{
448
0
    WOLFSSL_ENTER("wolfSSL_CONF_modules_load");
449
0
    WOLFSSL_MSG("All wolfSSL modules are already compiled in. "
450
0
                "wolfSSL_CONF_modules_load doesn't load anything new.");
451
0
    (void)cnf;
452
0
    (void)appname;
453
0
    (void)flags;
454
0
    return WOLFSSL_SUCCESS;
455
0
}
456
457
WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new(void)
458
0
{
459
0
    WOLFSSL_CONF_VALUE* ret;
460
461
0
    WOLFSSL_ENTER("wolfSSL_CONF_new");
462
463
0
    ret = (WOLFSSL_CONF_VALUE*)XMALLOC(sizeof(WOLFSSL_CONF_VALUE),
464
0
            NULL, DYNAMIC_TYPE_OPENSSL);
465
0
    if (ret)
466
0
        XMEMSET(ret, 0, sizeof(WOLFSSL_CONF_VALUE));
467
0
    return ret;
468
0
}
469
470
int wolfSSL_CONF_add_string(WOLFSSL_CONF *conf,
471
        WOLFSSL_CONF_VALUE *section, WOLFSSL_CONF_VALUE *value)
472
0
{
473
0
    WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
474
475
0
    if (!conf || !section || !value) {
476
0
        WOLFSSL_MSG("Bad parameter");
477
0
        return WOLFSSL_FAILURE;
478
0
    }
479
480
0
    sk = (WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *)section->value;
481
0
    value->section = section->section;
482
483
0
    if (wolfSSL_sk_CONF_VALUE_push(sk, value) <= 0) {
484
0
        WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
485
0
        return WOLFSSL_FAILURE;
486
0
    }
487
0
    if (wolfSSL_sk_CONF_VALUE_push(conf->data, value) <= 0) {
488
0
        WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
489
0
        wolfssl_sk_pop_type(sk, STACK_TYPE_CONF_VALUE);
490
0
        return WOLFSSL_FAILURE;
491
0
    }
492
493
0
    return WOLFSSL_SUCCESS;
494
0
}
495
496
WOLFSSL_CONF_VALUE *wolfSSL_CONF_new_section(WOLFSSL_CONF *conf,
497
        const char *section)
498
0
{
499
0
    WOLFSSL_CONF_VALUE* ret = NULL;
500
0
    WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
501
0
    int slen;
502
503
0
    WOLFSSL_ENTER("wolfSSL_CONF_new_section");
504
505
0
    if (!conf || !section) {
506
0
        WOLFSSL_MSG("Bad parameter");
507
0
        return NULL;
508
0
    }
509
510
0
    slen = (int)XSTRLEN(section);
511
512
0
    if (!(ret = wolfSSL_CONF_VALUE_new())) {
513
0
        WOLFSSL_MSG("wolfSSL_CONF_new error");
514
0
        goto error;
515
0
    }
516
517
0
    if (!(ret->section = (char*)XMALLOC(slen+1, NULL, DYNAMIC_TYPE_OPENSSL))) {
518
0
        WOLFSSL_MSG("section malloc error");
519
0
        goto error;
520
0
    }
521
0
    XMEMCPY(ret->section, section, slen+1);
522
523
0
    if (!(sk = wolfSSL_sk_CONF_VALUE_new(NULL))) {
524
0
        WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_new error");
525
0
        goto error;
526
0
    }
527
528
0
    ret->value = (char*)sk;
529
530
0
    if (wolfSSL_sk_CONF_VALUE_push(conf->data, ret) <= 0) {
531
0
        WOLFSSL_MSG("wolfSSL_sk_CONF_VALUE_push error");
532
0
        goto error;
533
0
    }
534
535
0
    return ret;
536
0
error:
537
0
    if (ret) {
538
        /* NULL so that wolfSSL_X509V3_conf_free doesn't attempt to free it */
539
0
        ret->value = NULL;
540
0
        wolfSSL_X509V3_conf_free(ret);
541
0
    }
542
0
    if (sk) {
543
0
        wolfSSL_sk_CONF_VALUE_free(sk);
544
0
    }
545
0
    return NULL;
546
0
}
547
548
WOLFSSL_CONF_VALUE *wolfSSL_CONF_get_section(WOLFSSL_CONF *conf,
549
        const char *section)
550
0
{
551
0
    WOLF_STACK_OF(WOLFSSL_CONF_VALUE) *sk = NULL;
552
553
0
    WOLFSSL_ENTER("wolfSSL_CONF_get_section");
554
555
0
    if (!conf || !section) {
556
0
        WOLFSSL_MSG("Bad parameter");
557
0
        return NULL;
558
0
    }
559
560
0
    sk = conf->data;
561
562
0
    while (sk) {
563
0
        WOLFSSL_CONF_VALUE* val = sk->data.conf;
564
0
        if (val) {
565
0
            if (!val->name && XSTRCMP(section, val->section) == 0) {
566
0
                return val;
567
0
            }
568
0
        }
569
0
        sk = sk->next;
570
0
    }
571
572
0
    return NULL;
573
0
}
574
575
WOLFSSL_CONF *wolfSSL_NCONF_new(void *meth)
576
0
{
577
0
    WOLFSSL_CONF* ret;
578
0
    WOLFSSL_ENTER("wolfSSL_NCONF_new");
579
580
0
    if (meth) {
581
0
        WOLFSSL_MSG("wolfSSL does not support CONF_METHOD");
582
0
    }
583
584
0
    ret = (WOLFSSL_CONF*)XMALLOC(sizeof(WOLFSSL_CONF), NULL, DYNAMIC_TYPE_OPENSSL);
585
0
    if (ret) {
586
0
        XMEMSET(ret, 0, sizeof(WOLFSSL_CONF));
587
0
        ret->data = wolfSSL_sk_CONF_VALUE_new(NULL);
588
0
        if (!ret->data) {
589
0
            wolfSSL_NCONF_free(ret);
590
0
            return NULL;
591
0
        }
592
0
    }
593
0
    return ret;
594
0
}
595
596
char *wolfSSL_NCONF_get_string(const WOLFSSL_CONF *conf,
597
        const char *group, const char *name)
598
0
{
599
0
    WOLFSSL_CONF_VALUE find_val;
600
0
    WOLFSSL_CONF_VALUE *val;
601
0
    WOLFSSL_ENTER("wolfSSL_NCONF_get_string");
602
603
0
    if (!conf) {
604
#ifdef HAVE_SECURE_GETENV
605
        return secure_getenv(name);
606
#else
607
0
        WOLFSSL_MSG("Missing secure_getenv");
608
0
        return NULL;
609
0
#endif
610
0
    }
611
612
0
    find_val.name = (char *)name;
613
0
    if (group) {
614
0
        find_val.section = (char *)group;
615
0
        val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
616
0
        if (val)
617
0
            return val->value;
618
0
        if (XSTRCMP(group, "ENV") == 0) {
619
#ifdef HAVE_SECURE_GETENV
620
            return secure_getenv(name);
621
#else
622
0
        WOLFSSL_MSG("Missing secure_getenv");
623
0
            return NULL;
624
0
#endif
625
0
        }
626
0
    }
627
628
0
    find_val.section = (char *)"default";
629
0
    val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
630
0
    if (val)
631
0
        return val->value;
632
0
    else
633
0
        return NULL;
634
0
}
635
636
int wolfSSL_NCONF_get_number(const WOLFSSL_CONF *conf, const char *group,
637
        const char *name, long *result)
638
0
{
639
0
    char *str;
640
0
    WOLFSSL_ENTER("wolfSSL_NCONF_get_number");
641
642
0
    if (!conf || !name || !result) {
643
0
        WOLFSSL_MSG("Bad parameter");
644
0
        return WOLFSSL_FAILURE;
645
0
    }
646
647
0
    if (!(str = wolfSSL_NCONF_get_string(conf, group, name))) {
648
0
        WOLFSSL_MSG("wolfSSL_NCONF_get_string error");
649
0
        return WOLFSSL_FAILURE;
650
0
    }
651
652
0
    *result = atol(str);
653
0
    return WOLFSSL_SUCCESS;
654
0
}
655
656
/**
657
 * The WOLFSSL_CONF->value member is treated as a
658
 * WOLFSSL_STACK_OF(WOLFSSL_CONF_VALUE) which becomes
659
 * the return value.
660
 * @param conf
661
 * @param section
662
 * @return WOLFSSL_STACK_OF(WOLFSSL_CONF_VALUE)
663
 */
664
WOLFSSL_STACK *wolfSSL_NCONF_get_section(
665
        const WOLFSSL_CONF *conf, const char *section)
666
0
{
667
0
    WOLFSSL_CONF_VALUE *val;
668
0
    WOLFSSL_CONF_VALUE find_val;
669
670
0
    WOLFSSL_ENTER("wolfSSL_NCONF_get_section");
671
672
0
    if (!conf || !section) {
673
0
        WOLFSSL_MSG("Bad parameter");
674
0
        return NULL;
675
0
    }
676
677
0
    find_val.name = NULL;
678
0
    find_val.section = (char*)section;
679
0
    val = wolfSSL_lh_WOLFSSL_CONF_VALUE_retrieve(conf->data, &find_val);
680
0
    if (val)
681
0
        return (WOLFSSL_STACK*)val->value;
682
0
    else
683
0
        return NULL;
684
0
}
685
686
#if  !defined(NO_BIO)
687
static WOLFSSL_CONF_VALUE *wolfSSL_CONF_VALUE_new_values(char* section,
688
        char* name, char* value)
689
0
{
690
0
    WOLFSSL_CONF_VALUE* ret;
691
0
    int len;
692
693
0
    WOLFSSL_ENTER("wolfSSL_CONF_VALUE_new_values");
694
695
0
    if (!(ret = wolfSSL_CONF_VALUE_new())) {
696
0
        WOLFSSL_MSG("wolfSSL_CONF_VALUE_new error");
697
0
        return NULL;
698
0
    }
699
700
0
    if (section) {
701
0
        len = (int)XSTRLEN(section);
702
0
        ret->section = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
703
0
        if (!ret->section) {
704
0
            WOLFSSL_MSG("malloc error");
705
0
            wolfSSL_X509V3_conf_free(ret);
706
0
            return NULL;
707
0
        }
708
0
        XMEMCPY(ret->section, section, len+1);
709
0
    }
710
711
0
    if (name) {
712
0
        len = (int)XSTRLEN(name);
713
0
        ret->name = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
714
0
        if (!ret->name) {
715
0
            WOLFSSL_MSG("malloc error");
716
0
            wolfSSL_X509V3_conf_free(ret);
717
0
            return NULL;
718
0
        }
719
0
        XMEMCPY(ret->name, name, len+1);
720
0
    }
721
722
0
    if (value) {
723
0
        len = (int)XSTRLEN(value);
724
0
        ret->value = (char*)XMALLOC(len+1, NULL, DYNAMIC_TYPE_OPENSSL);
725
0
        if (!ret->value) {
726
0
            WOLFSSL_MSG("malloc error");
727
0
            wolfSSL_X509V3_conf_free(ret);
728
0
            return NULL;
729
0
        }
730
0
        XMEMCPY(ret->value, value, len+1);
731
0
    }
732
733
0
    return ret;
734
0
}
735
736
static char* expandValue(WOLFSSL_CONF *conf, const char* section,
737
        char *str)
738
0
{
739
0
    int strLen = (int)XSTRLEN(str);
740
0
    char* ret = NULL;
741
742
    /* Check to see if there is anything to expand */
743
0
    if (XSTRNSTR(str, "$", strLen)) {
744
0
        int idx = 0;
745
0
        char* strIdx = str;
746
0
        ret = (char*)XMALLOC(strLen + 1, NULL, DYNAMIC_TYPE_OPENSSL);
747
0
        if (!ret) {
748
0
            WOLFSSL_MSG("malloc error");
749
0
            return str;
750
0
        }
751
752
0
        while (*strIdx) {
753
0
            if (*strIdx == '$') {
754
                /* Expand variable */
755
0
                char* startIdx = ++strIdx;
756
0
                char* endIdx;
757
0
                const char* s = section;
758
0
                const char* value;
759
0
                char prevValue;
760
761
0
                if (*startIdx == '{') {
762
                    /* First read the section.
763
                     * format: ${section_name::var_name} */
764
0
                    s = ++startIdx;
765
0
                    while (*strIdx && *strIdx != ':') strIdx++;
766
0
                    if (!*strIdx || s == strIdx || strIdx[1] != ':') {
767
0
                        WOLFSSL_MSG("invalid section name in "
768
0
                                    "variable expansion");
769
0
                        goto expand_cleanup;
770
0
                    }
771
0
                    *strIdx = '\0';
772
0
                    strIdx += 2;
773
0
                    startIdx = strIdx;
774
0
                }
775
0
                while (*strIdx && (XISALNUM((unsigned char)*strIdx) || *strIdx == '_'))
776
0
                    strIdx++;
777
0
                endIdx = strIdx;
778
0
                if (startIdx == endIdx) {
779
0
                    WOLFSSL_MSG("invalid variable name in config");
780
0
                    goto expand_cleanup;
781
0
                }
782
0
                if (s != section) {
783
                    /* We are expecting a trailing '}' */
784
0
                    if (*strIdx != '}') {
785
0
                        WOLFSSL_MSG("Missing '}' in variable");
786
0
                        goto expand_cleanup;
787
0
                    }
788
0
                    strIdx++;
789
0
                }
790
                /* Save char value at the end of the name so that we can place
791
                 * a null char there. */
792
0
                prevValue = *endIdx;
793
0
                *endIdx = '\0';
794
0
                value = wolfSSL_NCONF_get_string(conf, s, startIdx);
795
0
                *endIdx = prevValue;
796
                /* Skip copy if no value or zero-length value */
797
0
                if (value && *value) {
798
0
                    int valueLen = (int)XSTRLEN(value);
799
0
                    char* newRet;
800
                    /* This will allocate slightly more memory than necessary
801
                     * but better be safe */
802
0
                    strLen += valueLen;
803
                #ifdef WOLFSSL_NO_REALLOC
804
                    newRet = (char*)XMALLOC(strLen + 1, NULL,
805
                            DYNAMIC_TYPE_OPENSSL);
806
                    if (newRet != NULL && ret != NULL) {
807
                       XMEMCPY(newRet, ret, (strLen - valueLen) + 1);
808
                       XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
809
                       ret = NULL;
810
                    }
811
                #else
812
0
                    newRet = (char*)XREALLOC(ret, strLen + 1, NULL,
813
0
                            DYNAMIC_TYPE_OPENSSL);
814
0
                #endif
815
0
                    if (!newRet) {
816
0
                        WOLFSSL_MSG("realloc error");
817
0
                        goto expand_cleanup;
818
0
                    }
819
0
                    ret = newRet;
820
0
                    XMEMCPY(ret + idx, value, valueLen);
821
0
                    idx += valueLen;
822
0
                }
823
0
            }
824
0
            else {
825
0
                ret[idx++] = *strIdx++;
826
0
            }
827
0
        }
828
0
        ret[idx] = '\0';
829
0
    }
830
831
0
    return ret ? ret : str;
832
833
0
expand_cleanup:
834
0
    XFREE(ret, NULL, DYNAMIC_TYPE_OPENSSL);
835
0
    return NULL;
836
0
}
837
838
#define SKIP_WHITESPACE(idx, max_idx) \
839
0
    while ((idx) < (max_idx) && (*(idx) == ' ' || *(idx) == '\t'))      \
840
0
        {(idx)++;}
841
int wolfSSL_NCONF_load(WOLFSSL_CONF *conf, const char *file, long *eline)
842
0
{
843
0
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
844
0
    WOLFSSL_BIO *in = NULL;
845
0
    char* buf = NULL;
846
0
    char* idx = NULL;
847
0
    char* bufEnd = NULL;
848
0
    CONF_VALUE* section = NULL;
849
0
    long line = 0;
850
0
    int bufLen = 0;
851
852
0
    if (!conf || !file) {
853
0
        WOLFSSL_MSG("Bad parameter");
854
0
        return WOLFSSL_FAILURE;
855
0
    }
856
857
    /* Open file */
858
0
    if (!(in = wolfSSL_BIO_new_file(file, "rb"))) {
859
0
        WOLFSSL_MSG("wolfSSL_BIO_new_file error");
860
0
        return WOLFSSL_FAILURE;
861
0
    }
862
863
    /* Read file */
864
0
    bufLen = wolfSSL_BIO_get_len(in);
865
0
    if (bufLen <= 0) {
866
0
        WOLFSSL_MSG("wolfSSL_BIO_get_len error");
867
0
        goto cleanup;
868
0
    }
869
0
    if (!(buf = (char*)XMALLOC(bufLen + 1, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
870
0
        WOLFSSL_MSG("malloc error");
871
0
        goto cleanup;
872
0
    }
873
0
    if (wolfSSL_BIO_read(in, buf, bufLen) != bufLen) {
874
0
        WOLFSSL_MSG("wolfSSL_BIO_read error");
875
0
        goto cleanup;
876
0
    }
877
878
0
    if (!(section = wolfSSL_CONF_new_section(conf, "default"))) {
879
0
        WOLFSSL_MSG("wolfSSL_CONF_new_section error");
880
0
        goto cleanup;
881
0
    }
882
883
    /* LETS START READING SOME CONFIGS */
884
0
    idx = buf;
885
0
    bufEnd = buf + bufLen;
886
0
    while (idx < bufEnd) {
887
0
        char* lineEnd = XSTRNSTR(idx, "\n", (size_t)(bufEnd - idx));
888
0
        char* maxIdx;
889
0
        if (!lineEnd)
890
0
            lineEnd = bufEnd; /* Last line in file */
891
0
        maxIdx = XSTRNSTR(idx, "#", (size_t)(lineEnd - idx));
892
0
        if (!maxIdx)
893
0
            maxIdx = lineEnd;
894
0
        line++;
895
0
        SKIP_WHITESPACE(idx, maxIdx);
896
0
        if (idx == maxIdx) {
897
            /* Empty line */
898
0
            idx = lineEnd + 1;
899
0
            continue;
900
0
        }
901
902
0
        if (*idx == '[') {
903
            /* New section. Spaces not allowed in section name. */
904
0
            char* sectionName;
905
0
            int sectionNameLen;
906
907
0
            if (idx < maxIdx)
908
0
                idx++;
909
0
            else {
910
0
                WOLFSSL_MSG("Invalid section definition.");
911
0
                goto cleanup;
912
0
            }
913
914
0
            SKIP_WHITESPACE(idx, maxIdx);
915
0
            sectionName = idx;
916
            /* Find end of section name */
917
0
            while (idx < maxIdx && *idx != ' ' && *idx != ']')
918
0
                idx++;
919
0
            sectionNameLen = (int)(idx - sectionName);
920
0
            SKIP_WHITESPACE(idx, maxIdx);
921
922
0
            if (*idx != ']') {
923
0
                WOLFSSL_MSG("Section definition error. "
924
0
                            "Closing brace not found.");
925
0
                goto cleanup;
926
0
            }
927
928
0
            sectionName[sectionNameLen] = '\0';
929
0
            if (!(section = wolfSSL_CONF_get_section(conf, sectionName))) {
930
0
                section = wolfSSL_CONF_new_section(conf, sectionName);
931
0
                if (!section)
932
0
                    goto cleanup;
933
0
            }
934
0
        }
935
0
        else {
936
0
            char* name;
937
0
            int   nameLen;
938
0
            char* value;
939
0
            char* exValue; /* expanded value */
940
0
            int   valueLen;
941
0
            WOLFSSL_CONF_VALUE* newVal = NULL;
942
943
0
            SKIP_WHITESPACE(idx, maxIdx);
944
0
            name = idx;
945
            /* Find end of name */
946
0
            while (idx < maxIdx && *idx != ' ' && *idx != '=')
947
0
                idx++;
948
0
            nameLen = (int)(idx - name);
949
0
            SKIP_WHITESPACE(idx, maxIdx);
950
0
            if (*idx != '=') {
951
0
                WOLFSSL_MSG("Missing equals sign");
952
0
                goto cleanup;
953
0
            }
954
0
            idx++;
955
0
            SKIP_WHITESPACE(idx, maxIdx);
956
0
            value = idx;
957
            /* Find end of value */
958
0
            idx = maxIdx-1;
959
0
            while (idx >= value && (*idx == ' ' || *idx == '\t' || *idx == '\r'))
960
0
                idx--;
961
0
            valueLen = (int)(idx - value + 1);
962
963
            /* Sanity checks */
964
0
            if (nameLen <= 0 || valueLen <= 0) {
965
0
                WOLFSSL_MSG("Sanity checks failed");
966
0
                goto cleanup;
967
0
            }
968
0
            name[nameLen] = '\0';
969
0
            value[valueLen] = '\0';
970
971
0
            if (!(exValue = expandValue(conf, section->section, value))) {
972
0
                WOLFSSL_MSG("Variable expansion failed");
973
0
                goto cleanup;
974
0
            }
975
976
0
            if (!(newVal = wolfSSL_CONF_VALUE_new_values(NULL,
977
0
                    name, exValue))) {
978
0
                WOLFSSL_MSG("wolfSSL_CONF_VALUE_new_values error");
979
0
                if (exValue != value)
980
0
                    XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
981
0
                goto cleanup;
982
0
            }
983
984
0
            if (exValue != value)
985
0
                XFREE(exValue, NULL, DYNAMIC_TYPE_OPENSSL);
986
987
0
            if (wolfSSL_CONF_add_string(conf, section, newVal) !=
988
0
                    WOLFSSL_SUCCESS) {
989
0
                wolfSSL_X509V3_conf_free(newVal);
990
0
                WOLFSSL_MSG("wolfSSL_CONF_add_string error");
991
0
                goto cleanup;
992
0
            }
993
0
        }
994
0
        idx = lineEnd + 1;
995
0
    }
996
997
0
    ret = WOLFSSL_SUCCESS;
998
0
cleanup:
999
0
    if (in)
1000
0
        wolfSSL_BIO_free(in);
1001
0
    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1002
0
    if (eline)
1003
0
        *eline = line;
1004
0
    return ret;
1005
0
}
1006
#endif /* !NO_BIO */
1007
1008
void wolfSSL_NCONF_free(WOLFSSL_CONF *conf)
1009
0
{
1010
0
    WOLFSSL_ENTER("wolfSSL_NCONF_free");
1011
0
    if (conf) {
1012
0
        wolfSSL_sk_CONF_VALUE_free(conf->data);
1013
0
        XFREE(conf, NULL, DYNAMIC_TYPE_OPENSSL);
1014
0
    }
1015
0
}
1016
1017
void wolfSSL_X509V3_conf_free(WOLFSSL_CONF_VALUE *val)
1018
0
{
1019
0
    if (val) {
1020
0
        if (val->name) {
1021
            /* Not a section. Don't free section as it is a shared pointer. */
1022
0
            XFREE(val->name, NULL, DYNAMIC_TYPE_OPENSSL);
1023
0
            XFREE(val->value, NULL, DYNAMIC_TYPE_OPENSSL);
1024
0
        }
1025
0
        else {
1026
            /* Section so val->value is a stack */
1027
0
            XFREE(val->section, NULL, DYNAMIC_TYPE_OPENSSL);
1028
            /* Only free the stack structures. The contained conf values
1029
             * will be freed in wolfSSL_NCONF_free */
1030
0
            wolfSSL_sk_free((WOLF_STACK_OF(WOLFSSL_CONF_VALUE)*)val->value);
1031
0
        }
1032
0
        XFREE(val, NULL, DYNAMIC_TYPE_OPENSSL);
1033
0
    }
1034
0
}
1035
1036
WOLFSSL_STACK *wolfSSL_sk_CONF_VALUE_new(
1037
    WOLF_SK_COMPARE_CB(WOLFSSL_CONF_VALUE, compFunc))
1038
0
{
1039
0
    WOLFSSL_STACK* ret;
1040
0
    WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_new");
1041
0
    ret = wolfSSL_sk_new_node(NULL);
1042
0
    if (!ret)
1043
0
        return NULL;
1044
0
    ret->hash_fn = (wolf_sk_hash_cb)wolfSSL_CONF_VALUE_hash;
1045
0
    ret->type = STACK_TYPE_CONF_VALUE;
1046
0
    (void)compFunc;
1047
0
    return ret;
1048
0
}
1049
1050
/* Free the structure for WOLFSSL_CONF_VALUE stack
1051
 *
1052
 * sk  stack to free nodes in
1053
 */
1054
void wolfSSL_sk_CONF_VALUE_free(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk)
1055
0
{
1056
0
    WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_free");
1057
1058
0
    wolfSSL_sk_pop_free(sk, NULL);
1059
0
}
1060
1061
int wolfSSL_sk_CONF_VALUE_num(const WOLFSSL_STACK *sk)
1062
0
{
1063
0
    WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_num");
1064
0
    if (sk)
1065
0
        return wolfSSL_sk_num(sk);
1066
0
    return 0;
1067
0
}
1068
1069
WOLFSSL_CONF_VALUE *wolfSSL_sk_CONF_VALUE_value(const WOLFSSL_STACK *sk, int i)
1070
0
{
1071
0
    WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_value");
1072
0
    if (sk)
1073
0
        return (WOLFSSL_CONF_VALUE*)wolfSSL_sk_value(sk, i);
1074
0
    return NULL;
1075
0
}
1076
1077
/* return 1 on success 0 on fail */
1078
int wolfSSL_sk_CONF_VALUE_push(WOLF_STACK_OF(WOLFSSL_CONF_VALUE)* sk,
1079
        WOLFSSL_CONF_VALUE* val)
1080
0
{
1081
0
    WOLFSSL_ENTER("wolfSSL_sk_CONF_VALUE_push");
1082
1083
0
    if (sk == NULL || val == NULL) {
1084
0
        return WOLFSSL_FAILURE;
1085
0
    }
1086
1087
0
    return wolfSSL_sk_push(sk, val);
1088
0
}
1089
1090
#endif /* !NO_CERTS && OPENSSL_EXTRA && OPENSSL_ALL */
1091
1092
#ifdef OPENSSL_EXTRA
1093
#ifndef NO_WOLFSSL_STUB
1094
/* Returns default file name and path of config file. However
1095
   a wolfssl.cnf file is not currently supported */
1096
char* wolfSSL_CONF_get1_default_config_file(void)
1097
0
{
1098
0
    WOLFSSL_ENTER("wolfSSL_CONF_get1_default_config_file");
1099
0
    WOLFSSL_STUB("CONF_get1_default_config_file");
1100
0
    return NULL;
1101
0
}
1102
#endif
1103
1104
/**
1105
 * Allocate WOLFSSL_CONF_CTX instance
1106
 * @return pointer to WOLFSSL_CONF_CTX structure on success and NULL on fail
1107
 */
1108
WOLFSSL_CONF_CTX* wolfSSL_CONF_CTX_new(void)
1109
0
{
1110
0
    WOLFSSL_CONF_CTX* cctx;
1111
1112
0
    WOLFSSL_ENTER("wolfSSL_CONF_CTX_new");
1113
1114
0
    cctx = (WOLFSSL_CONF_CTX*)XMALLOC(sizeof(WOLFSSL_CONF_CTX), NULL,
1115
0
                                                    DYNAMIC_TYPE_OPENSSL);
1116
0
    if (!cctx) {
1117
0
        WOLFSSL_MSG("malloc error");
1118
0
        return NULL;
1119
0
    }
1120
0
    XMEMSET(cctx, 0, sizeof(WOLFSSL_CONF_CTX));
1121
1122
0
    return cctx;
1123
0
}
1124
/**
1125
 * Release WOLFSSL_CONF_CTX instance
1126
 * @param cctx a pointer to WOLFSSL_CONF_CTX structure to be freed
1127
 */
1128
void wolfSSL_CONF_CTX_free(WOLFSSL_CONF_CTX* cctx)
1129
0
{
1130
0
    WOLFSSL_ENTER("wolfSSL_CONF_CTX_free");
1131
1132
0
    XFREE(cctx, NULL, DYNAMIC_TYPE_OPENSSL);
1133
1134
0
    WOLFSSL_LEAVE("wolfSSL_CONF_CTX_free", 1);
1135
0
}
1136
/**
1137
 * Set WOLFSSL_CTX instance to WOLFSSL_CONF_CTX
1138
 * @param cctx a pointer to WOLFSSL_CONF_CTX structure to set a WOLFSSL_CTX
1139
 *             pointer to its ctx
1140
 * @param ctx  a pointer to WOLFSSL_CTX structure to be set
1141
 */
1142
void wolfSSL_CONF_CTX_set_ssl_ctx(WOLFSSL_CONF_CTX* cctx, WOLFSSL_CTX *ctx)
1143
0
{
1144
0
    WOLFSSL_ENTER("wolfSSL_CONF_CTX_set_ssl_ctx");
1145
1146
    /* sanity check */
1147
0
    if (cctx == NULL) {
1148
0
        WOLFSSL_MSG("cctx is null");
1149
0
        return;
1150
0
    }
1151
1152
0
    cctx->ctx = ctx;
1153
0
    WOLFSSL_LEAVE("wolfSSL_CONF_CTX_set_ssl_ctx", 1);
1154
0
}
1155
/**
1156
 * set flag value into WOLFSSL_CONF_CTX
1157
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure to be set
1158
 * @param flags flag value to be OR'd
1159
 * @return OR'd flag value, otherwise 0
1160
 */
1161
unsigned int wolfSSL_CONF_CTX_set_flags(WOLFSSL_CONF_CTX* cctx,
1162
                                                            unsigned int flags)
1163
0
{
1164
    /* sanity check */
1165
0
    if (cctx == NULL)
1166
0
        return 0;
1167
1168
0
    cctx->flags |= flags;
1169
0
    return cctx->flags;
1170
0
}
1171
1172
/**
1173
 * finish configuration command operation
1174
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure to be set
1175
 * @return WOLFSSL_SUCCESS on success
1176
 */
1177
int wolfSSL_CONF_CTX_finish(WOLFSSL_CONF_CTX* cctx)
1178
0
{
1179
0
    (void)cctx;
1180
0
    return WOLFSSL_SUCCESS;
1181
0
}
1182
/*
1183
 * The following definitions and static functions are used for
1184
 * wolfSSL_CONF_cmd() to handle command.
1185
 *
1186
 * Definitions below are a part of conf_cmds_tbl[] contents.
1187
 *  WOLFSSL_CONF_FILE_CMDx  represents command name in configuration file
1188
 *  WOLFSSL_CONF_CMDL_CMDx  represents command name on command line
1189
 *
1190
 * The static functions after the definition section process
1191
 *                 those FILE or CMDL which are defined in the conf_cmds_tbl.
1192
 *
1193
 * To add a new command handling:
1194
 *  1. Add new #define to a section of WOLFSSL_CONF_FILE_CMD* and
1195
 *                                      WOLFSSL_CONF_CMDL_CMD*
1196
 *  2. Add new static function after #define section, before
1197
 *                      "typedef struct conf_cmd_tbl {" line
1198
 *  3. Add new entry to conf_cmds_tbl[] by following other command entries
1199
 */
1200
#define WOLFSSL_CONF_FILE_CMD1  "Curves"
1201
#define WOLFSSL_CONF_FILE_CMD2  "Certificate"
1202
#define WOLFSSL_CONF_FILE_CMD3  "PrivateKey"
1203
#define WOLFSSL_CONF_FILE_CMD4  "Protocol"
1204
#define WOLFSSL_CONF_FILE_CMD5  "Options"
1205
#define WOLFSSL_CONF_FILE_CMD6  "ServerInfoFile"
1206
#define WOLFSSL_CONF_FILE_CMD7  "SignatureAlgorithms"
1207
#define WOLFSSL_CONF_FILE_CMD8  "ClientSignatureAlgorithms"
1208
#define WOLFSSL_CONF_FILE_CMD9  "CipherString"
1209
1210
#define WOLFSSL_CONF_CMDL_CMD1  "curves"
1211
#define WOLFSSL_CONF_CMDL_CMD2  "cert"
1212
#define WOLFSSL_CONF_CMDL_CMD3  "key"
1213
#define WOLFSSL_CONF_CMDL_CMD4  NULL
1214
#define WOLFSSL_CONF_CMDL_CMD5  NULL
1215
#define WOLFSSL_CONF_CMDL_CMD6  NULL
1216
#define WOLFSSL_CONF_CMDL_CMD7  "sigalgs"
1217
#define WOLFSSL_CONF_CMDL_CMD8  "client_sigalgs"
1218
#define WOLFSSL_CONF_CMDL_CMD9  "cipher"
1219
1220
#if !defined(NO_DH) && !defined(NO_BIO)
1221
#define WOLFSSL_CONF_FILE_CMD10 "DHParameters"
1222
#define WOLFSSL_CONF_CMDL_CMD10 "dhparam"
1223
#endif
1224
1225
#ifdef HAVE_ECC
1226
#define WOLFSSL_CONF_FILE_CMD11 "ECDHParameters"
1227
#define WOLFSSL_CONF_CMDL_CMD11 "named_curves"
1228
#endif
1229
1230
/**
1231
 * process Cipher String command
1232
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure
1233
 * @param value arguments for cmd
1234
 * @return WOLFSSL_SUCCESS on success,
1235
 *     otherwise WOLFSSL_FAILURE or
1236
 *               -3 if value is null or
1237
 *               negative value on other failure
1238
 */
1239
static int cmdfunc_cipherstring(WOLFSSL_CONF_CTX* cctx, const char* value)
1240
0
{
1241
0
    int ret = -3;
1242
1243
0
    WOLFSSL_ENTER("cmdfunc_cipherstring");
1244
1245
     /* sanity check */
1246
0
    if (cctx == NULL)
1247
0
        return WOLFSSL_FAILURE;
1248
1249
0
    if (value == NULL) {
1250
0
        WOLFSSL_MSG("bad arguments");
1251
0
        return ret;
1252
0
    }
1253
1254
0
    if (cctx->ctx) {
1255
0
        ret = wolfSSL_CTX_set_cipher_list(cctx->ctx, value);
1256
0
    }
1257
1258
0
    if (((cctx->ctx  && ret == WOLFSSL_SUCCESS) ||
1259
0
         (!cctx->ctx && ret == -3)) &&
1260
0
        cctx->ssl) {
1261
0
        ret = wolfSSL_set_cipher_list(cctx->ssl, value);
1262
0
    }
1263
1264
0
    WOLFSSL_LEAVE("cmdfunc_cipherstring", ret);
1265
0
    return ret;
1266
0
}
1267
1268
/**
1269
 * process curves command
1270
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure
1271
 * @param value arguments for cmd
1272
 * @return WOLFSSL_SUCCESS on success,
1273
 *     otherwise WOLFSSL_FAILURE or
1274
 *               -3 if value is null or
1275
 *               negative value on other failure
1276
 */
1277
#if defined(HAVE_ECC)
1278
static int cmdfunc_curves(WOLFSSL_CONF_CTX* cctx, const char* value)
1279
0
{
1280
0
    int ret = -3;
1281
1282
0
    WOLFSSL_ENTER("cmdfunc_curves");
1283
1284
     /* sanity check */
1285
0
    if (cctx == NULL)
1286
0
        return WOLFSSL_FAILURE;
1287
1288
0
    if (value == NULL) {
1289
0
        WOLFSSL_MSG("bad arguments");
1290
0
        return ret;
1291
0
    }
1292
1293
0
    if (cctx->ctx) {
1294
0
        ret = wolfSSL_CTX_set1_curves_list(cctx->ctx, value);
1295
0
    }
1296
1297
0
    if (((cctx->ctx  && ret == WOLFSSL_SUCCESS) ||
1298
0
         (!cctx->ctx && ret == -3)) &&
1299
0
        cctx->ssl) {
1300
0
        ret = wolfSSL_set1_curves_list(cctx->ssl, value);
1301
0
    }
1302
1303
0
    WOLFSSL_LEAVE("cmdfunc_curves", ret);
1304
0
    return ret;
1305
0
}
1306
#endif
1307
1308
#ifndef NO_FILESYSTEM
1309
/**
1310
 * process cert command
1311
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure
1312
 * @param value arguments for cmd
1313
 * @return WOLFSSL_SUCCESS on success,
1314
 *     otherwise WOLFSSL_FAILURE or
1315
 *               -3 if value is null or
1316
 *               negative value on other failure
1317
 */
1318
static int cmdfunc_cert(WOLFSSL_CONF_CTX* cctx, const char* value)
1319
0
{
1320
0
    int ret = -3;
1321
1322
0
    WOLFSSL_ENTER("cmdfunc_cert");
1323
1324
    /* sanity check */
1325
0
    if (cctx == NULL)
1326
0
        return WOLFSSL_FAILURE;
1327
1328
0
    if (value == NULL) {
1329
0
        WOLFSSL_MSG("bad arguments");
1330
0
        return ret;
1331
0
    }
1332
1333
0
    if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) {
1334
0
        WOLFSSL_MSG("certificate flag is not set");
1335
0
        return -2;
1336
0
    }
1337
1338
0
    if (cctx->ctx) {
1339
0
        ret = wolfSSL_CTX_use_certificate_chain_file(cctx->ctx, value);
1340
0
    }
1341
1342
0
    if (((cctx->ctx  && ret == WOLFSSL_SUCCESS) ||
1343
0
         (!cctx->ctx && ret == -3)) &&
1344
0
        cctx->ssl) {
1345
0
        ret = wolfSSL_use_certificate_file(cctx->ssl, value,
1346
0
                                                    WOLFSSL_FILETYPE_PEM);
1347
0
    }
1348
1349
0
    WOLFSSL_LEAVE("cmdfunc_cert", ret);
1350
0
    return ret;
1351
0
}
1352
/**
1353
 * process key command
1354
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure
1355
 * @param value arguments for cmd
1356
 * @return WOLFSSL_SUCCESS on success,
1357
 *     otherwise WOLFSSL_FAILURE or
1358
 *               -3 if value is null or
1359
 *               negative value on other failure
1360
 */
1361
static int cmdfunc_key(WOLFSSL_CONF_CTX* cctx, const char* value)
1362
0
{
1363
0
    int ret = -3;
1364
1365
0
    WOLFSSL_ENTER("cmdfunc_key");
1366
1367
     /* sanity check */
1368
0
    if (cctx == NULL)
1369
0
        return WOLFSSL_FAILURE;
1370
1371
0
    if (value == NULL) {
1372
0
        WOLFSSL_MSG("bad arguments");
1373
0
        return ret;
1374
0
    }
1375
1376
0
    if (!(cctx->flags & WOLFSSL_CONF_FLAG_CERTIFICATE)) {
1377
0
        WOLFSSL_MSG("certificate flag is not set");
1378
0
        return -2;
1379
0
    }
1380
1381
0
    if (cctx->ctx) {
1382
0
        ret = wolfSSL_CTX_use_PrivateKey_file(cctx->ctx, value,
1383
0
                                                    WOLFSSL_FILETYPE_PEM);
1384
0
    }
1385
1386
0
    if (((cctx->ctx  && ret == WOLFSSL_SUCCESS) ||
1387
0
         (!cctx->ctx && ret == -3)) &&
1388
0
        cctx->ssl) {
1389
0
        ret = wolfSSL_use_PrivateKey_file(cctx->ssl, value,
1390
0
                                                    WOLFSSL_FILETYPE_PEM);
1391
0
    }
1392
1393
0
    WOLFSSL_LEAVE("cmdfunc_key", ret);
1394
0
    return ret;
1395
0
}
1396
#endif /* NO_FILESYSTEM */
1397
/**
1398
 * process DH parameter command
1399
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure
1400
 * @param value arguments for cmd
1401
 * @return WOLFSSL_SUCCESS on success,
1402
 *     otherwise WOLFSSL_FAILURE or
1403
 *               -3 if value is null or
1404
 *               negative value on other failure
1405
 */
1406
#if !defined(NO_DH) && !defined(NO_BIO)
1407
static int cmdfunc_dhparam(WOLFSSL_CONF_CTX* cctx, const char* value)
1408
0
{
1409
0
    int ret = -3;
1410
0
    WOLFSSL_DH* dh = NULL;
1411
0
    WOLFSSL_BIO* bio = NULL;
1412
1413
0
    WOLFSSL_MSG("cmdfunc_dhparam");
1414
1415
     /* sanity check */
1416
0
    if (cctx == NULL)
1417
0
        return WOLFSSL_FAILURE;
1418
1419
0
    if (value == NULL) {
1420
0
        WOLFSSL_MSG("bad arguments");
1421
0
        return ret;
1422
0
    }
1423
1424
0
    if (cctx->ctx || cctx->ssl) {
1425
0
        bio = wolfSSL_BIO_new_file(value, "rb");
1426
0
        if (!bio) {
1427
0
            WOLFSSL_MSG("bio new file failed");
1428
0
            return WOLFSSL_FAILURE;
1429
0
        }
1430
0
        dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
1431
0
        if (!dh) {
1432
0
            wolfSSL_BIO_free(bio);
1433
0
            WOLFSSL_MSG("PEM read bio failed");
1434
0
            return WOLFSSL_FAILURE;
1435
0
        }
1436
0
    } else {
1437
0
        return 1;
1438
0
    }
1439
1440
0
    if (cctx->ctx) {
1441
0
        ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ctx, dh);
1442
0
    }
1443
1444
0
    if (((cctx->ctx  && ret == WOLFSSL_SUCCESS) ||
1445
0
         (!cctx->ctx && ret == -3)) &&
1446
0
        cctx->ssl) {
1447
0
        ret = (int)wolfSSL_CTX_set_tmp_dh(cctx->ssl->ctx, dh);
1448
0
    }
1449
1450
0
    if (dh)
1451
0
        wolfSSL_DH_free(dh);
1452
0
    if (bio)
1453
0
        wolfSSL_BIO_free(bio);
1454
1455
0
    WOLFSSL_LEAVE("cmdfunc_dhparam", ret);
1456
0
    return ret;
1457
0
}
1458
#endif /* !NO_DH && !NO_BIO */
1459
/**
1460
 * command table
1461
 */
1462
typedef struct conf_cmd_tbl {
1463
    const char* file_cmd;
1464
    const char* cmdline_cmd;
1465
    word32 data_type;
1466
    int (*cmdfunc)(WOLFSSL_CONF_CTX* cctx, const char* value);
1467
}conf_cmd_tbl;
1468
1469
static const conf_cmd_tbl conf_cmds_tbl[] = {
1470
#if defined(HAVE_ECC)
1471
    /* cmd Curves */
1472
    {WOLFSSL_CONF_FILE_CMD1, WOLFSSL_CONF_CMDL_CMD1,
1473
                                    WOLFSSL_CONF_TYPE_STRING, cmdfunc_curves},
1474
#endif
1475
#if !defined(NO_FILESYSTEM)
1476
    /* cmd Certificate */
1477
    {WOLFSSL_CONF_FILE_CMD2, WOLFSSL_CONF_CMDL_CMD2,
1478
                                    WOLFSSL_CONF_TYPE_FILE, cmdfunc_cert},
1479
    /* cmd PrivateKey */
1480
    {WOLFSSL_CONF_FILE_CMD3, WOLFSSL_CONF_CMDL_CMD3,
1481
                                    WOLFSSL_CONF_TYPE_FILE, cmdfunc_key},
1482
#endif
1483
    /* cmd Protocol */
1484
    {WOLFSSL_CONF_FILE_CMD4, WOLFSSL_CONF_CMDL_CMD4,
1485
                                    WOLFSSL_CONF_TYPE_STRING, NULL},
1486
    /* cmd Options */
1487
    {WOLFSSL_CONF_FILE_CMD5, WOLFSSL_CONF_CMDL_CMD5,
1488
                                    WOLFSSL_CONF_TYPE_STRING, NULL},
1489
    /* cmd ServerInfoFile */
1490
    {WOLFSSL_CONF_FILE_CMD6, WOLFSSL_CONF_CMDL_CMD6,
1491
                                    WOLFSSL_CONF_TYPE_FILE, NULL},
1492
    /* cmd SignatureAlgorithms */
1493
    {WOLFSSL_CONF_FILE_CMD7, WOLFSSL_CONF_CMDL_CMD7,
1494
                                    WOLFSSL_CONF_TYPE_STRING, NULL},
1495
    /* cmd ClientSignatureAlgorithms */
1496
    {WOLFSSL_CONF_FILE_CMD8, WOLFSSL_CONF_CMDL_CMD8,
1497
                                    WOLFSSL_CONF_TYPE_STRING, NULL},
1498
    /* cmd CipherString */
1499
    {WOLFSSL_CONF_FILE_CMD9, WOLFSSL_CONF_CMDL_CMD9,
1500
                              WOLFSSL_CONF_TYPE_STRING, cmdfunc_cipherstring},
1501
#if !defined(NO_DH) && !defined(NO_BIO)
1502
    /* cmd DHParameters */
1503
    {WOLFSSL_CONF_FILE_CMD10, WOLFSSL_CONF_CMDL_CMD10,
1504
                                    WOLFSSL_CONF_TYPE_FILE, cmdfunc_dhparam},
1505
#endif
1506
#ifdef HAVE_ECC
1507
    /* cmd ECHDParameters */
1508
    {WOLFSSL_CONF_FILE_CMD11, WOLFSSL_CONF_CMDL_CMD11,
1509
                                    WOLFSSL_CONF_TYPE_STRING, NULL},
1510
#endif
1511
};
1512
/* size of command table */
1513
static const size_t size_of_cmd_tbls = sizeof(conf_cmds_tbl)
1514
                                                    / sizeof(conf_cmd_tbl);
1515
1516
static const conf_cmd_tbl* wolfssl_conf_find_cmd(WOLFSSL_CONF_CTX* cctx,
1517
                                         const char* cmd)
1518
0
{
1519
0
    size_t i = 0;
1520
1521
0
    if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) {
1522
0
        size_t cmdlen = XSTRLEN(cmd);
1523
1524
0
        if (cmdlen < 2) {
1525
0
            WOLFSSL_MSG("bad cmdline command");
1526
0
            return NULL;
1527
0
        }
1528
        /* skip "-" prefix */
1529
0
        ++cmd;
1530
0
    }
1531
1532
0
    for (i = 0; i < size_of_cmd_tbls; i++) {
1533
        /* check if the cmd is valid */
1534
0
        if (cctx->flags & WOLFSSL_CONF_FLAG_CMDLINE) {
1535
0
            if (conf_cmds_tbl[i].cmdline_cmd != NULL &&
1536
0
                XSTRCMP(cmd, conf_cmds_tbl[i].cmdline_cmd) == 0) {
1537
0
                return &conf_cmds_tbl[i];
1538
0
            }
1539
0
        }
1540
1541
0
        if (cctx->flags & WOLFSSL_CONF_FLAG_FILE) {
1542
0
            if (conf_cmds_tbl[i].file_cmd != NULL &&
1543
0
                XSTRCMP(cmd, conf_cmds_tbl[i].file_cmd) == 0) {
1544
0
                return &conf_cmds_tbl[i];
1545
0
            }
1546
0
        }
1547
0
    }
1548
1549
0
    return NULL;
1550
0
}
1551
1552
/**
1553
 * send configuration command
1554
 * @param cctx  a pointer to WOLFSSL_CONF_CTX structure
1555
 * @param cmd   configuration command
1556
 * @param value arguments for cmd
1557
 * @return 1 when cmd is recognised, but value is not used
1558
 *         2 both cmd and value are used
1559
 *  otherwise WOLFSSL_FAILURE
1560
 *         -2 if cmd is not recognised
1561
 *         -3 if value is NULL, but cmd is recognized
1562
 */
1563
int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
1564
0
{
1565
0
    int ret = WC_NO_ERR_TRACE(WOLFSSL_FAILURE);
1566
0
    const conf_cmd_tbl* confcmd = NULL;
1567
0
    WOLFSSL_ENTER("wolfSSL_CONF_cmd");
1568
1569
    /* sanity check */
1570
0
    if (cctx == NULL || cmd == NULL) {
1571
0
        WOLFSSL_MSG("bad arguments");
1572
0
        return ret;
1573
0
    }
1574
1575
0
    confcmd = wolfssl_conf_find_cmd(cctx, cmd);
1576
0
    if (confcmd == NULL)
1577
0
        return -2;
1578
1579
0
    if (confcmd->cmdfunc == NULL) {
1580
0
        WOLFSSL_MSG("cmd not yet implemented");
1581
0
        return -2;
1582
0
    }
1583
1584
0
    ret = confcmd->cmdfunc(cctx, value);
1585
1586
    /* return code compliant with OpenSSL */
1587
0
    if (ret < -3)
1588
0
        ret = 0;
1589
1590
0
    WOLFSSL_LEAVE("wolfSSL_CONF_cmd", ret);
1591
0
    return ret;
1592
0
}
1593
1594
/**
1595
 *
1596
 * @param cctx a pointer to WOLFSSL_CONF_CTX structure
1597
 * @param cmd  configuration command
1598
 * @return The SSL_CONF_TYPE_* type or SSL_CONF_TYPE_UNKNOWN if an
1599
 *         invalid command
1600
 */
1601
int wolfSSL_CONF_cmd_value_type(WOLFSSL_CONF_CTX *cctx, const char *cmd)
1602
0
{
1603
0
    const conf_cmd_tbl* confcmd = NULL;
1604
0
    WOLFSSL_ENTER("wolfSSL_CONF_cmd_value_type");
1605
1606
0
    confcmd = wolfssl_conf_find_cmd(cctx, cmd);
1607
0
    if (confcmd == NULL)
1608
0
        return WOLFSSL_CONF_TYPE_UNKNOWN;
1609
0
    return (int)confcmd->data_type;
1610
0
}
1611
1612
#endif /* OPENSSL_EXTRA */
1613
1614
1615
/*******************************************************************************
1616
 * END OF CONF API
1617
 ******************************************************************************/
1618
1619
#if defined(OPENSSL_EXTRA)
1620
WOLFSSL_INIT_SETTINGS* wolfSSL_OPENSSL_INIT_new(void)
1621
0
{
1622
0
    WOLFSSL_INIT_SETTINGS* init = (WOLFSSL_INIT_SETTINGS*)XMALLOC(
1623
0
            sizeof(WOLFSSL_INIT_SETTINGS), NULL, DYNAMIC_TYPE_OPENSSL);
1624
1625
0
    return init;
1626
0
}
1627
1628
void wolfSSL_OPENSSL_INIT_free(WOLFSSL_INIT_SETTINGS* init)
1629
0
{
1630
0
    XFREE(init, NULL, DYNAMIC_TYPE_OPENSSL);
1631
0
}
1632
1633
#ifndef NO_WOLFSSL_STUB
1634
int wolfSSL_OPENSSL_INIT_set_config_appname(WOLFSSL_INIT_SETTINGS* init,
1635
        char* appname)
1636
0
{
1637
0
    (void)init;
1638
0
    (void)appname;
1639
0
    WOLFSSL_STUB("OPENSSL_INIT_set_config_appname");
1640
0
    return WOLFSSL_SUCCESS;
1641
0
}
1642
#endif
1643
1644
#endif /* OPENSSL_EXTRA */
1645
1646
1647
1648
#endif /* WOLFSSL_CONF_INCLUDED */