xref: /third_party/openssl/crypto/txt_db/txt_db.c (revision e1051a39)
1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <stdio.h>
11e1051a39Sopenharmony_ci#include <stdlib.h>
12e1051a39Sopenharmony_ci#include <string.h>
13e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
14e1051a39Sopenharmony_ci#include <openssl/buffer.h>
15e1051a39Sopenharmony_ci#include <openssl/txt_db.h>
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#undef BUFSIZE
18e1051a39Sopenharmony_ci#define BUFSIZE 512
19e1051a39Sopenharmony_ci
20e1051a39Sopenharmony_ciTXT_DB *TXT_DB_read(BIO *in, int num)
21e1051a39Sopenharmony_ci{
22e1051a39Sopenharmony_ci    TXT_DB *ret = NULL;
23e1051a39Sopenharmony_ci    int esc = 0;
24e1051a39Sopenharmony_ci    int i, add, n;
25e1051a39Sopenharmony_ci    int size = BUFSIZE;
26e1051a39Sopenharmony_ci    int offset = 0;
27e1051a39Sopenharmony_ci    char *p, *f;
28e1051a39Sopenharmony_ci    OPENSSL_STRING *pp;
29e1051a39Sopenharmony_ci    BUF_MEM *buf = NULL;
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ci    if ((buf = BUF_MEM_new()) == NULL)
32e1051a39Sopenharmony_ci        goto err;
33e1051a39Sopenharmony_ci    if (!BUF_MEM_grow(buf, size))
34e1051a39Sopenharmony_ci        goto err;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
37e1051a39Sopenharmony_ci        goto err;
38e1051a39Sopenharmony_ci    ret->num_fields = num;
39e1051a39Sopenharmony_ci    ret->index = NULL;
40e1051a39Sopenharmony_ci    ret->qual = NULL;
41e1051a39Sopenharmony_ci    if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL)
42e1051a39Sopenharmony_ci        goto err;
43e1051a39Sopenharmony_ci    if ((ret->index = OPENSSL_malloc(sizeof(*ret->index) * num)) == NULL)
44e1051a39Sopenharmony_ci        goto err;
45e1051a39Sopenharmony_ci    if ((ret->qual = OPENSSL_malloc(sizeof(*(ret->qual)) * num)) == NULL)
46e1051a39Sopenharmony_ci        goto err;
47e1051a39Sopenharmony_ci    for (i = 0; i < num; i++) {
48e1051a39Sopenharmony_ci        ret->index[i] = NULL;
49e1051a39Sopenharmony_ci        ret->qual[i] = NULL;
50e1051a39Sopenharmony_ci    }
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci    add = (num + 1) * sizeof(char *);
53e1051a39Sopenharmony_ci    buf->data[size - 1] = '\0';
54e1051a39Sopenharmony_ci    offset = 0;
55e1051a39Sopenharmony_ci    for (;;) {
56e1051a39Sopenharmony_ci        if (offset != 0) {
57e1051a39Sopenharmony_ci            size += BUFSIZE;
58e1051a39Sopenharmony_ci            if (!BUF_MEM_grow_clean(buf, size))
59e1051a39Sopenharmony_ci                goto err;
60e1051a39Sopenharmony_ci        }
61e1051a39Sopenharmony_ci        buf->data[offset] = '\0';
62e1051a39Sopenharmony_ci        BIO_gets(in, &(buf->data[offset]), size - offset);
63e1051a39Sopenharmony_ci        if (buf->data[offset] == '\0')
64e1051a39Sopenharmony_ci            break;
65e1051a39Sopenharmony_ci        if ((offset == 0) && (buf->data[0] == '#'))
66e1051a39Sopenharmony_ci            continue;
67e1051a39Sopenharmony_ci        i = strlen(&(buf->data[offset]));
68e1051a39Sopenharmony_ci        offset += i;
69e1051a39Sopenharmony_ci        if (buf->data[offset - 1] != '\n')
70e1051a39Sopenharmony_ci            continue;
71e1051a39Sopenharmony_ci        else {
72e1051a39Sopenharmony_ci            buf->data[offset - 1] = '\0'; /* blat the '\n' */
73e1051a39Sopenharmony_ci            if ((p = OPENSSL_malloc(add + offset)) == NULL)
74e1051a39Sopenharmony_ci                goto err;
75e1051a39Sopenharmony_ci            offset = 0;
76e1051a39Sopenharmony_ci        }
77e1051a39Sopenharmony_ci        pp = (char **)p;
78e1051a39Sopenharmony_ci        p += add;
79e1051a39Sopenharmony_ci        n = 0;
80e1051a39Sopenharmony_ci        pp[n++] = p;
81e1051a39Sopenharmony_ci        i = 0;
82e1051a39Sopenharmony_ci        f = buf->data;
83e1051a39Sopenharmony_ci
84e1051a39Sopenharmony_ci        esc = 0;
85e1051a39Sopenharmony_ci        for (;;) {
86e1051a39Sopenharmony_ci            if (*f == '\0')
87e1051a39Sopenharmony_ci                break;
88e1051a39Sopenharmony_ci            if (*f == '\t') {
89e1051a39Sopenharmony_ci                if (esc)
90e1051a39Sopenharmony_ci                    p--;
91e1051a39Sopenharmony_ci                else {
92e1051a39Sopenharmony_ci                    *(p++) = '\0';
93e1051a39Sopenharmony_ci                    f++;
94e1051a39Sopenharmony_ci                    if (n >= num)
95e1051a39Sopenharmony_ci                        break;
96e1051a39Sopenharmony_ci                    pp[n++] = p;
97e1051a39Sopenharmony_ci                    continue;
98e1051a39Sopenharmony_ci                }
99e1051a39Sopenharmony_ci            }
100e1051a39Sopenharmony_ci            esc = (*f == '\\');
101e1051a39Sopenharmony_ci            *(p++) = *(f++);
102e1051a39Sopenharmony_ci        }
103e1051a39Sopenharmony_ci        *(p++) = '\0';
104e1051a39Sopenharmony_ci        if ((n != num) || (*f != '\0')) {
105e1051a39Sopenharmony_ci            OPENSSL_free(pp);
106e1051a39Sopenharmony_ci            ret->error = DB_ERROR_WRONG_NUM_FIELDS;
107e1051a39Sopenharmony_ci            goto err;
108e1051a39Sopenharmony_ci        }
109e1051a39Sopenharmony_ci        pp[n] = p;
110e1051a39Sopenharmony_ci        if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) {
111e1051a39Sopenharmony_ci            OPENSSL_free(pp);
112e1051a39Sopenharmony_ci            goto err;
113e1051a39Sopenharmony_ci        }
114e1051a39Sopenharmony_ci    }
115e1051a39Sopenharmony_ci    BUF_MEM_free(buf);
116e1051a39Sopenharmony_ci    return ret;
117e1051a39Sopenharmony_ci err:
118e1051a39Sopenharmony_ci    BUF_MEM_free(buf);
119e1051a39Sopenharmony_ci    if (ret != NULL) {
120e1051a39Sopenharmony_ci        sk_OPENSSL_PSTRING_free(ret->data);
121e1051a39Sopenharmony_ci        OPENSSL_free(ret->index);
122e1051a39Sopenharmony_ci        OPENSSL_free(ret->qual);
123e1051a39Sopenharmony_ci        OPENSSL_free(ret);
124e1051a39Sopenharmony_ci    }
125e1051a39Sopenharmony_ci    return NULL;
126e1051a39Sopenharmony_ci}
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ciOPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx,
129e1051a39Sopenharmony_ci                                    OPENSSL_STRING *value)
130e1051a39Sopenharmony_ci{
131e1051a39Sopenharmony_ci    OPENSSL_STRING *ret;
132e1051a39Sopenharmony_ci    LHASH_OF(OPENSSL_STRING) *lh;
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci    if (idx >= db->num_fields) {
135e1051a39Sopenharmony_ci        db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
136e1051a39Sopenharmony_ci        return NULL;
137e1051a39Sopenharmony_ci    }
138e1051a39Sopenharmony_ci    lh = db->index[idx];
139e1051a39Sopenharmony_ci    if (lh == NULL) {
140e1051a39Sopenharmony_ci        db->error = DB_ERROR_NO_INDEX;
141e1051a39Sopenharmony_ci        return NULL;
142e1051a39Sopenharmony_ci    }
143e1051a39Sopenharmony_ci    ret = lh_OPENSSL_STRING_retrieve(lh, value);
144e1051a39Sopenharmony_ci    db->error = DB_ERROR_OK;
145e1051a39Sopenharmony_ci    return ret;
146e1051a39Sopenharmony_ci}
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ciint TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *),
149e1051a39Sopenharmony_ci                        OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp)
150e1051a39Sopenharmony_ci{
151e1051a39Sopenharmony_ci    LHASH_OF(OPENSSL_STRING) *idx;
152e1051a39Sopenharmony_ci    OPENSSL_STRING *r, *k;
153e1051a39Sopenharmony_ci    int i, n;
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_ci    if (field >= db->num_fields) {
156e1051a39Sopenharmony_ci        db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
157e1051a39Sopenharmony_ci        return 0;
158e1051a39Sopenharmony_ci    }
159e1051a39Sopenharmony_ci    /* FIXME: we lose type checking at this point */
160e1051a39Sopenharmony_ci    if ((idx = (LHASH_OF(OPENSSL_STRING) *)OPENSSL_LH_new(hash, cmp)) == NULL) {
161e1051a39Sopenharmony_ci        db->error = DB_ERROR_MALLOC;
162e1051a39Sopenharmony_ci        return 0;
163e1051a39Sopenharmony_ci    }
164e1051a39Sopenharmony_ci    n = sk_OPENSSL_PSTRING_num(db->data);
165e1051a39Sopenharmony_ci    for (i = 0; i < n; i++) {
166e1051a39Sopenharmony_ci        r = sk_OPENSSL_PSTRING_value(db->data, i);
167e1051a39Sopenharmony_ci        if ((qual != NULL) && (qual(r) == 0))
168e1051a39Sopenharmony_ci            continue;
169e1051a39Sopenharmony_ci        if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
170e1051a39Sopenharmony_ci            db->error = DB_ERROR_INDEX_CLASH;
171e1051a39Sopenharmony_ci            db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k);
172e1051a39Sopenharmony_ci            db->arg2 = i;
173e1051a39Sopenharmony_ci            lh_OPENSSL_STRING_free(idx);
174e1051a39Sopenharmony_ci            return 0;
175e1051a39Sopenharmony_ci        }
176e1051a39Sopenharmony_ci        if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) {
177e1051a39Sopenharmony_ci            db->error = DB_ERROR_MALLOC;
178e1051a39Sopenharmony_ci            lh_OPENSSL_STRING_free(idx);
179e1051a39Sopenharmony_ci            return 0;
180e1051a39Sopenharmony_ci        }
181e1051a39Sopenharmony_ci    }
182e1051a39Sopenharmony_ci    lh_OPENSSL_STRING_free(db->index[field]);
183e1051a39Sopenharmony_ci    db->index[field] = idx;
184e1051a39Sopenharmony_ci    db->qual[field] = qual;
185e1051a39Sopenharmony_ci    return 1;
186e1051a39Sopenharmony_ci}
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_cilong TXT_DB_write(BIO *out, TXT_DB *db)
189e1051a39Sopenharmony_ci{
190e1051a39Sopenharmony_ci    long i, j, n, nn, l, tot = 0;
191e1051a39Sopenharmony_ci    char *p, **pp, *f;
192e1051a39Sopenharmony_ci    BUF_MEM *buf = NULL;
193e1051a39Sopenharmony_ci    long ret = -1;
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci    if ((buf = BUF_MEM_new()) == NULL)
196e1051a39Sopenharmony_ci        goto err;
197e1051a39Sopenharmony_ci    n = sk_OPENSSL_PSTRING_num(db->data);
198e1051a39Sopenharmony_ci    nn = db->num_fields;
199e1051a39Sopenharmony_ci    for (i = 0; i < n; i++) {
200e1051a39Sopenharmony_ci        pp = sk_OPENSSL_PSTRING_value(db->data, i);
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci        l = 0;
203e1051a39Sopenharmony_ci        for (j = 0; j < nn; j++) {
204e1051a39Sopenharmony_ci            if (pp[j] != NULL)
205e1051a39Sopenharmony_ci                l += strlen(pp[j]);
206e1051a39Sopenharmony_ci        }
207e1051a39Sopenharmony_ci        if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn)))
208e1051a39Sopenharmony_ci            goto err;
209e1051a39Sopenharmony_ci
210e1051a39Sopenharmony_ci        p = buf->data;
211e1051a39Sopenharmony_ci        for (j = 0; j < nn; j++) {
212e1051a39Sopenharmony_ci            f = pp[j];
213e1051a39Sopenharmony_ci            if (f != NULL)
214e1051a39Sopenharmony_ci                for (;;) {
215e1051a39Sopenharmony_ci                    if (*f == '\0')
216e1051a39Sopenharmony_ci                        break;
217e1051a39Sopenharmony_ci                    if (*f == '\t')
218e1051a39Sopenharmony_ci                        *(p++) = '\\';
219e1051a39Sopenharmony_ci                    *(p++) = *(f++);
220e1051a39Sopenharmony_ci                }
221e1051a39Sopenharmony_ci            *(p++) = '\t';
222e1051a39Sopenharmony_ci        }
223e1051a39Sopenharmony_ci        p[-1] = '\n';
224e1051a39Sopenharmony_ci        j = p - buf->data;
225e1051a39Sopenharmony_ci        if (BIO_write(out, buf->data, (int)j) != j)
226e1051a39Sopenharmony_ci            goto err;
227e1051a39Sopenharmony_ci        tot += j;
228e1051a39Sopenharmony_ci    }
229e1051a39Sopenharmony_ci    ret = tot;
230e1051a39Sopenharmony_ci err:
231e1051a39Sopenharmony_ci    BUF_MEM_free(buf);
232e1051a39Sopenharmony_ci    return ret;
233e1051a39Sopenharmony_ci}
234e1051a39Sopenharmony_ci
235e1051a39Sopenharmony_ciint TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
236e1051a39Sopenharmony_ci{
237e1051a39Sopenharmony_ci    int i;
238e1051a39Sopenharmony_ci    OPENSSL_STRING *r;
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_ci    for (i = 0; i < db->num_fields; i++) {
241e1051a39Sopenharmony_ci        if (db->index[i] != NULL) {
242e1051a39Sopenharmony_ci            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
243e1051a39Sopenharmony_ci                continue;
244e1051a39Sopenharmony_ci            r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
245e1051a39Sopenharmony_ci            if (r != NULL) {
246e1051a39Sopenharmony_ci                db->error = DB_ERROR_INDEX_CLASH;
247e1051a39Sopenharmony_ci                db->arg1 = i;
248e1051a39Sopenharmony_ci                db->arg_row = r;
249e1051a39Sopenharmony_ci                goto err;
250e1051a39Sopenharmony_ci            }
251e1051a39Sopenharmony_ci        }
252e1051a39Sopenharmony_ci    }
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_ci    for (i = 0; i < db->num_fields; i++) {
255e1051a39Sopenharmony_ci        if (db->index[i] != NULL) {
256e1051a39Sopenharmony_ci            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
257e1051a39Sopenharmony_ci                continue;
258e1051a39Sopenharmony_ci            (void)lh_OPENSSL_STRING_insert(db->index[i], row);
259e1051a39Sopenharmony_ci            if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL)
260e1051a39Sopenharmony_ci                goto err1;
261e1051a39Sopenharmony_ci        }
262e1051a39Sopenharmony_ci    }
263e1051a39Sopenharmony_ci    if (!sk_OPENSSL_PSTRING_push(db->data, row))
264e1051a39Sopenharmony_ci        goto err1;
265e1051a39Sopenharmony_ci    return 1;
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_ci err1:
268e1051a39Sopenharmony_ci    db->error = DB_ERROR_MALLOC;
269e1051a39Sopenharmony_ci    while (i-- > 0) {
270e1051a39Sopenharmony_ci        if (db->index[i] != NULL) {
271e1051a39Sopenharmony_ci            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
272e1051a39Sopenharmony_ci                continue;
273e1051a39Sopenharmony_ci            (void)lh_OPENSSL_STRING_delete(db->index[i], row);
274e1051a39Sopenharmony_ci        }
275e1051a39Sopenharmony_ci    }
276e1051a39Sopenharmony_ci err:
277e1051a39Sopenharmony_ci    return 0;
278e1051a39Sopenharmony_ci}
279e1051a39Sopenharmony_ci
280e1051a39Sopenharmony_civoid TXT_DB_free(TXT_DB *db)
281e1051a39Sopenharmony_ci{
282e1051a39Sopenharmony_ci    int i, n;
283e1051a39Sopenharmony_ci    char **p, *max;
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ci    if (db == NULL)
286e1051a39Sopenharmony_ci        return;
287e1051a39Sopenharmony_ci    if (db->index != NULL) {
288e1051a39Sopenharmony_ci        for (i = db->num_fields - 1; i >= 0; i--)
289e1051a39Sopenharmony_ci            lh_OPENSSL_STRING_free(db->index[i]);
290e1051a39Sopenharmony_ci        OPENSSL_free(db->index);
291e1051a39Sopenharmony_ci    }
292e1051a39Sopenharmony_ci    OPENSSL_free(db->qual);
293e1051a39Sopenharmony_ci    if (db->data != NULL) {
294e1051a39Sopenharmony_ci        for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
295e1051a39Sopenharmony_ci            /*
296e1051a39Sopenharmony_ci             * check if any 'fields' have been allocated from outside of the
297e1051a39Sopenharmony_ci             * initial block
298e1051a39Sopenharmony_ci             */
299e1051a39Sopenharmony_ci            p = sk_OPENSSL_PSTRING_value(db->data, i);
300e1051a39Sopenharmony_ci            max = p[db->num_fields]; /* last address */
301e1051a39Sopenharmony_ci            if (max == NULL) {  /* new row */
302e1051a39Sopenharmony_ci                for (n = 0; n < db->num_fields; n++)
303e1051a39Sopenharmony_ci                    OPENSSL_free(p[n]);
304e1051a39Sopenharmony_ci            } else {
305e1051a39Sopenharmony_ci                for (n = 0; n < db->num_fields; n++) {
306e1051a39Sopenharmony_ci                    if (((p[n] < (char *)p) || (p[n] > max)))
307e1051a39Sopenharmony_ci                        OPENSSL_free(p[n]);
308e1051a39Sopenharmony_ci                }
309e1051a39Sopenharmony_ci            }
310e1051a39Sopenharmony_ci            OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i));
311e1051a39Sopenharmony_ci        }
312e1051a39Sopenharmony_ci        sk_OPENSSL_PSTRING_free(db->data);
313e1051a39Sopenharmony_ci    }
314e1051a39Sopenharmony_ci    OPENSSL_free(db);
315e1051a39Sopenharmony_ci}
316