Coverage Report

Created: 2022-11-30 06:20

/src/openssl/crypto/txt_db/txt_db.c
Line
Count
Source (jump to first uncovered line)
1
/* crypto/txt_db/txt_db.c */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3
 * All rights reserved.
4
 *
5
 * This package is an SSL implementation written
6
 * by Eric Young (eay@cryptsoft.com).
7
 * The implementation was written so as to conform with Netscapes SSL.
8
 *
9
 * This library is free for commercial and non-commercial use as long as
10
 * the following conditions are aheared to.  The following conditions
11
 * apply to all code found in this distribution, be it the RC4, RSA,
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13
 * included with this distribution is covered by the same copyright terms
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15
 *
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
17
 * the code are not to be removed.
18
 * If this package is used in a product, Eric Young should be given attribution
19
 * as the author of the parts of the library used.
20
 * This can be in the form of a textual message at program startup or
21
 * in documentation (online or textual) provided with the package.
22
 *
23
 * Redistribution and use in source and binary forms, with or without
24
 * modification, are permitted provided that the following conditions
25
 * are met:
26
 * 1. Redistributions of source code must retain the copyright
27
 *    notice, this list of conditions and the following disclaimer.
28
 * 2. Redistributions in binary form must reproduce the above copyright
29
 *    notice, this list of conditions and the following disclaimer in the
30
 *    documentation and/or other materials provided with the distribution.
31
 * 3. All advertising materials mentioning features or use of this software
32
 *    must display the following acknowledgement:
33
 *    "This product includes cryptographic software written by
34
 *     Eric Young (eay@cryptsoft.com)"
35
 *    The word 'cryptographic' can be left out if the rouines from the library
36
 *    being used are not cryptographic related :-).
37
 * 4. If you include any Windows specific code (or a derivative thereof) from
38
 *    the apps directory (application code) you must include an acknowledgement:
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * SUCH DAMAGE.
52
 *
53
 * The licence and distribution terms for any publically available version or
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55
 * copied and put under another distribution licence
56
 * [including the GNU Public Licence.]
57
 */
58
59
#include <stdio.h>
60
#include <stdlib.h>
61
#include <string.h>
62
#include "cryptlib.h"
63
#include <openssl/buffer.h>
64
#include <openssl/txt_db.h>
65
66
#undef BUFSIZE
67
0
#define BUFSIZE 512
68
69
const char TXT_DB_version[] = "TXT_DB" OPENSSL_VERSION_PTEXT;
70
71
TXT_DB *TXT_DB_read(BIO *in, int num)
72
0
{
73
0
    TXT_DB *ret = NULL;
74
0
    int er = 1;
75
0
    int esc = 0;
76
0
    long ln = 0;
77
0
    int i, add, n;
78
0
    int size = BUFSIZE;
79
0
    int offset = 0;
80
0
    char *p, *f;
81
0
    OPENSSL_STRING *pp;
82
0
    BUF_MEM *buf = NULL;
83
84
0
    if ((buf = BUF_MEM_new()) == NULL)
85
0
        goto err;
86
0
    if (!BUF_MEM_grow(buf, size))
87
0
        goto err;
88
89
0
    if ((ret = OPENSSL_malloc(sizeof(TXT_DB))) == NULL)
90
0
        goto err;
91
0
    ret->num_fields = num;
92
0
    ret->index = NULL;
93
0
    ret->qual = NULL;
94
0
    if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL)
95
0
        goto err;
96
0
    if ((ret->index = OPENSSL_malloc(sizeof(*ret->index) * num)) == NULL)
97
0
        goto err;
98
0
    if ((ret->qual = OPENSSL_malloc(sizeof(*(ret->qual)) * num)) == NULL)
99
0
        goto err;
100
0
    for (i = 0; i < num; i++) {
101
0
        ret->index[i] = NULL;
102
0
        ret->qual[i] = NULL;
103
0
    }
104
105
0
    add = (num + 1) * sizeof(char *);
106
0
    buf->data[size - 1] = '\0';
107
0
    offset = 0;
108
0
    for (;;) {
109
0
        if (offset != 0) {
110
0
            size += BUFSIZE;
111
0
            if (!BUF_MEM_grow_clean(buf, size))
112
0
                goto err;
113
0
        }
114
0
        buf->data[offset] = '\0';
115
0
        BIO_gets(in, &(buf->data[offset]), size - offset);
116
0
        ln++;
117
0
        if (buf->data[offset] == '\0')
118
0
            break;
119
0
        if ((offset == 0) && (buf->data[0] == '#'))
120
0
            continue;
121
0
        i = strlen(&(buf->data[offset]));
122
0
        offset += i;
123
0
        if (buf->data[offset - 1] != '\n')
124
0
            continue;
125
0
        else {
126
0
            buf->data[offset - 1] = '\0'; /* blat the '\n' */
127
0
            if (!(p = OPENSSL_malloc(add + offset)))
128
0
                goto err;
129
0
            offset = 0;
130
0
        }
131
0
        pp = (char **)p;
132
0
        p += add;
133
0
        n = 0;
134
0
        pp[n++] = p;
135
0
        i = 0;
136
0
        f = buf->data;
137
138
0
        esc = 0;
139
0
        for (;;) {
140
0
            if (*f == '\0')
141
0
                break;
142
0
            if (*f == '\t') {
143
0
                if (esc)
144
0
                    p--;
145
0
                else {
146
0
                    *(p++) = '\0';
147
0
                    f++;
148
0
                    if (n >= num)
149
0
                        break;
150
0
                    pp[n++] = p;
151
0
                    continue;
152
0
                }
153
0
            }
154
0
            esc = (*f == '\\');
155
0
            *(p++) = *(f++);
156
0
        }
157
0
        *(p++) = '\0';
158
0
        if ((n != num) || (*f != '\0')) {
159
0
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporary
160
                                                               * fix :-( */
161
0
            fprintf(stderr,
162
0
                    "wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",
163
0
                    ln, num, n, f);
164
0
#endif
165
0
            OPENSSL_free(pp);
166
0
            er = 2;
167
0
            goto err;
168
0
        }
169
0
        pp[n] = p;
170
0
        if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) {
171
0
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16) /* temporary
172
                                                               * fix :-( */
173
0
            fprintf(stderr, "failure in sk_push\n");
174
0
#endif
175
0
            OPENSSL_free(pp);
176
0
            er = 2;
177
0
            goto err;
178
0
        }
179
0
    }
180
0
    er = 0;
181
0
 err:
182
0
    BUF_MEM_free(buf);
183
0
    if (er) {
184
0
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)
185
0
        if (er == 1)
186
0
            fprintf(stderr, "OPENSSL_malloc failure\n");
187
0
#endif
188
0
        if (ret != NULL) {
189
0
            if (ret->data != NULL)
190
0
                sk_OPENSSL_PSTRING_free(ret->data);
191
0
            if (ret->index != NULL)
192
0
                OPENSSL_free(ret->index);
193
0
            if (ret->qual != NULL)
194
0
                OPENSSL_free(ret->qual);
195
0
            if (ret != NULL)
196
0
                OPENSSL_free(ret);
197
0
        }
198
0
        return (NULL);
199
0
    } else
200
0
        return (ret);
201
0
}
202
203
OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx,
204
                                    OPENSSL_STRING *value)
205
0
{
206
0
    OPENSSL_STRING *ret;
207
0
    LHASH_OF(OPENSSL_STRING) *lh;
208
209
0
    if (idx >= db->num_fields) {
210
0
        db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
211
0
        return (NULL);
212
0
    }
213
0
    lh = db->index[idx];
214
0
    if (lh == NULL) {
215
0
        db->error = DB_ERROR_NO_INDEX;
216
0
        return (NULL);
217
0
    }
218
0
    ret = lh_OPENSSL_STRING_retrieve(lh, value);
219
0
    db->error = DB_ERROR_OK;
220
0
    return (ret);
221
0
}
222
223
int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *),
224
                        LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
225
0
{
226
0
    LHASH_OF(OPENSSL_STRING) *idx;
227
0
    OPENSSL_STRING *r, *k;
228
0
    int i, n;
229
230
0
    if (field >= db->num_fields) {
231
0
        db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
232
0
        return (0);
233
0
    }
234
    /* FIXME: we lose type checking at this point */
235
0
    if ((idx = (LHASH_OF(OPENSSL_STRING) *)lh_new(hash, cmp)) == NULL) {
236
0
        db->error = DB_ERROR_MALLOC;
237
0
        return (0);
238
0
    }
239
0
    n = sk_OPENSSL_PSTRING_num(db->data);
240
0
    for (i = 0; i < n; i++) {
241
0
        r = sk_OPENSSL_PSTRING_value(db->data, i);
242
0
        if ((qual != NULL) && (qual(r) == 0))
243
0
            continue;
244
0
        if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
245
0
            db->error = DB_ERROR_INDEX_CLASH;
246
0
            db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k);
247
0
            db->arg2 = i;
248
0
            lh_OPENSSL_STRING_free(idx);
249
0
            return (0);
250
0
        }
251
0
        if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) {
252
0
            db->error = DB_ERROR_MALLOC;
253
0
            lh_OPENSSL_STRING_free(idx);
254
0
            return (0);
255
0
        }
256
0
    }
257
0
    if (db->index[field] != NULL)
258
0
        lh_OPENSSL_STRING_free(db->index[field]);
259
0
    db->index[field] = idx;
260
0
    db->qual[field] = qual;
261
0
    return (1);
262
0
}
263
264
long TXT_DB_write(BIO *out, TXT_DB *db)
265
0
{
266
0
    long i, j, n, nn, l, tot = 0;
267
0
    char *p, **pp, *f;
268
0
    BUF_MEM *buf = NULL;
269
0
    long ret = -1;
270
271
0
    if ((buf = BUF_MEM_new()) == NULL)
272
0
        goto err;
273
0
    n = sk_OPENSSL_PSTRING_num(db->data);
274
0
    nn = db->num_fields;
275
0
    for (i = 0; i < n; i++) {
276
0
        pp = sk_OPENSSL_PSTRING_value(db->data, i);
277
278
0
        l = 0;
279
0
        for (j = 0; j < nn; j++) {
280
0
            if (pp[j] != NULL)
281
0
                l += strlen(pp[j]);
282
0
        }
283
0
        if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn)))
284
0
            goto err;
285
286
0
        p = buf->data;
287
0
        for (j = 0; j < nn; j++) {
288
0
            f = pp[j];
289
0
            if (f != NULL)
290
0
                for (;;) {
291
0
                    if (*f == '\0')
292
0
                        break;
293
0
                    if (*f == '\t')
294
0
                        *(p++) = '\\';
295
0
                    *(p++) = *(f++);
296
0
                }
297
0
            *(p++) = '\t';
298
0
        }
299
0
        p[-1] = '\n';
300
0
        j = p - buf->data;
301
0
        if (BIO_write(out, buf->data, (int)j) != j)
302
0
            goto err;
303
0
        tot += j;
304
0
    }
305
0
    ret = tot;
306
0
 err:
307
0
    if (buf != NULL)
308
0
        BUF_MEM_free(buf);
309
0
    return (ret);
310
0
}
311
312
int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
313
0
{
314
0
    int i;
315
0
    OPENSSL_STRING *r;
316
317
0
    for (i = 0; i < db->num_fields; i++) {
318
0
        if (db->index[i] != NULL) {
319
0
            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
320
0
                continue;
321
0
            r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
322
0
            if (r != NULL) {
323
0
                db->error = DB_ERROR_INDEX_CLASH;
324
0
                db->arg1 = i;
325
0
                db->arg_row = r;
326
0
                goto err;
327
0
            }
328
0
        }
329
0
    }
330
331
0
    for (i = 0; i < db->num_fields; i++) {
332
0
        if (db->index[i] != NULL) {
333
0
            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
334
0
                continue;
335
0
            (void)lh_OPENSSL_STRING_insert(db->index[i], row);
336
0
            if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL)
337
0
                goto err1;
338
0
        }
339
0
    }
340
0
    if (!sk_OPENSSL_PSTRING_push(db->data, row))
341
0
        goto err1;
342
0
    return (1);
343
344
0
 err1:
345
0
    db->error = DB_ERROR_MALLOC;
346
0
    while (i-- > 0) {
347
0
        if (db->index[i] != NULL) {
348
0
            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
349
0
                continue;
350
0
            (void)lh_OPENSSL_STRING_delete(db->index[i], row);
351
0
        }
352
0
    }
353
0
 err:
354
0
    return (0);
355
0
}
356
357
void TXT_DB_free(TXT_DB *db)
358
0
{
359
0
    int i, n;
360
0
    char **p, *max;
361
362
0
    if (db == NULL)
363
0
        return;
364
365
0
    if (db->index != NULL) {
366
0
        for (i = db->num_fields - 1; i >= 0; i--)
367
0
            if (db->index[i] != NULL)
368
0
                lh_OPENSSL_STRING_free(db->index[i]);
369
0
        OPENSSL_free(db->index);
370
0
    }
371
0
    if (db->qual != NULL)
372
0
        OPENSSL_free(db->qual);
373
0
    if (db->data != NULL) {
374
0
        for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
375
            /*
376
             * check if any 'fields' have been allocated from outside of the
377
             * initial block
378
             */
379
0
            p = sk_OPENSSL_PSTRING_value(db->data, i);
380
0
            max = p[db->num_fields]; /* last address */
381
0
            if (max == NULL) {  /* new row */
382
0
                for (n = 0; n < db->num_fields; n++)
383
0
                    if (p[n] != NULL)
384
0
                        OPENSSL_free(p[n]);
385
0
            } else {
386
0
                for (n = 0; n < db->num_fields; n++) {
387
0
                    if (((p[n] < (char *)p) || (p[n] > max))
388
0
                        && (p[n] != NULL))
389
0
                        OPENSSL_free(p[n]);
390
0
                }
391
0
            }
392
0
            OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i));
393
0
        }
394
0
        sk_OPENSSL_PSTRING_free(db->data);
395
0
    }
396
0
    OPENSSL_free(db);
397
0
}