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