]>
Commit | Line | Data |
---|---|---|
aa6bb135 RS |
1 | /* |
2 | * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. | |
d02b48c6 | 3 | * |
aa6bb135 RS |
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 | |
d02b48c6 RE |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
b39fc560 | 13 | #include "internal/cryptlib.h" |
ec577822 BM |
14 | #include <openssl/buffer.h> |
15 | #include <openssl/txt_db.h> | |
d02b48c6 RE |
16 | |
17 | #undef BUFSIZE | |
0f113f3e | 18 | #define BUFSIZE 512 |
d02b48c6 | 19 | |
6b691a5c | 20 | TXT_DB *TXT_DB_read(BIO *in, int num) |
0f113f3e MC |
21 | { |
22 | TXT_DB *ret = NULL; | |
0f113f3e MC |
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; | |
d02b48c6 | 31 | |
0f113f3e MC |
32 | if ((buf = BUF_MEM_new()) == NULL) |
33 | goto err; | |
34 | if (!BUF_MEM_grow(buf, size)) | |
35 | goto err; | |
d02b48c6 | 36 | |
b4faea50 | 37 | if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) |
0f113f3e MC |
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 | } | |
d02b48c6 | 52 | |
0f113f3e MC |
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' */ | |
75ebbd9a | 75 | if ((p = OPENSSL_malloc(add + offset)) == NULL) |
0f113f3e MC |
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; | |
d02b48c6 | 85 | |
0f113f3e MC |
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')) { | |
9ad52c56 | 107 | OPENSSL_free(pp); |
51b04a61 | 108 | ret->error = DB_ERROR_WRONG_NUM_FIELDS; |
0f113f3e MC |
109 | goto err; |
110 | } | |
111 | pp[n] = p; | |
9ad52c56 BE |
112 | if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) { |
113 | OPENSSL_free(pp); | |
0f113f3e | 114 | goto err; |
9ad52c56 | 115 | } |
0f113f3e | 116 | } |
25aaa98a RS |
117 | BUF_MEM_free(buf); |
118 | return ret; | |
0f113f3e MC |
119 | err: |
120 | BUF_MEM_free(buf); | |
25aaa98a RS |
121 | if (ret != NULL) { |
122 | sk_OPENSSL_PSTRING_free(ret->data); | |
123 | OPENSSL_free(ret->index); | |
124 | OPENSSL_free(ret->qual); | |
125 | OPENSSL_free(ret); | |
126 | } | |
127 | return (NULL); | |
0f113f3e | 128 | } |
d02b48c6 | 129 | |
0f113f3e MC |
130 | OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, |
131 | OPENSSL_STRING *value) | |
132 | { | |
133 | OPENSSL_STRING *ret; | |
134 | LHASH_OF(OPENSSL_STRING) *lh; | |
d02b48c6 | 135 | |
0f113f3e MC |
136 | if (idx >= db->num_fields) { |
137 | db->error = DB_ERROR_INDEX_OUT_OF_RANGE; | |
138 | return (NULL); | |
139 | } | |
140 | lh = db->index[idx]; | |
141 | if (lh == NULL) { | |
142 | db->error = DB_ERROR_NO_INDEX; | |
143 | return (NULL); | |
144 | } | |
145 | ret = lh_OPENSSL_STRING_retrieve(lh, value); | |
146 | db->error = DB_ERROR_OK; | |
147 | return (ret); | |
148 | } | |
d02b48c6 | 149 | |
0f113f3e | 150 | int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *), |
739a1eb1 | 151 | OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp) |
0f113f3e MC |
152 | { |
153 | LHASH_OF(OPENSSL_STRING) *idx; | |
9ad52c56 | 154 | OPENSSL_STRING *r, *k; |
0f113f3e | 155 | int i, n; |
d02b48c6 | 156 | |
0f113f3e MC |
157 | if (field >= db->num_fields) { |
158 | db->error = DB_ERROR_INDEX_OUT_OF_RANGE; | |
159 | return (0); | |
160 | } | |
161 | /* FIXME: we lose type checking at this point */ | |
739a1eb1 | 162 | if ((idx = (LHASH_OF(OPENSSL_STRING) *)OPENSSL_LH_new(hash, cmp)) == NULL) { |
0f113f3e MC |
163 | db->error = DB_ERROR_MALLOC; |
164 | return (0); | |
165 | } | |
166 | n = sk_OPENSSL_PSTRING_num(db->data); | |
167 | for (i = 0; i < n; i++) { | |
168 | r = sk_OPENSSL_PSTRING_value(db->data, i); | |
169 | if ((qual != NULL) && (qual(r) == 0)) | |
170 | continue; | |
9ad52c56 | 171 | if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) { |
0f113f3e | 172 | db->error = DB_ERROR_INDEX_CLASH; |
9ad52c56 | 173 | db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k); |
0f113f3e MC |
174 | db->arg2 = i; |
175 | lh_OPENSSL_STRING_free(idx); | |
176 | return (0); | |
177 | } | |
9ad52c56 BE |
178 | if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) { |
179 | db->error = DB_ERROR_MALLOC; | |
180 | lh_OPENSSL_STRING_free(idx); | |
181 | return (0); | |
182 | } | |
0f113f3e | 183 | } |
25aaa98a | 184 | lh_OPENSSL_STRING_free(db->index[field]); |
0f113f3e MC |
185 | db->index[field] = idx; |
186 | db->qual[field] = qual; | |
208fb891 | 187 | return 1; |
0f113f3e | 188 | } |
d02b48c6 | 189 | |
6b691a5c | 190 | long TXT_DB_write(BIO *out, TXT_DB *db) |
0f113f3e MC |
191 | { |
192 | long i, j, n, nn, l, tot = 0; | |
193 | char *p, **pp, *f; | |
194 | BUF_MEM *buf = NULL; | |
195 | long ret = -1; | |
d02b48c6 | 196 | |
0f113f3e MC |
197 | if ((buf = BUF_MEM_new()) == NULL) |
198 | goto err; | |
199 | n = sk_OPENSSL_PSTRING_num(db->data); | |
200 | nn = db->num_fields; | |
201 | for (i = 0; i < n; i++) { | |
202 | pp = sk_OPENSSL_PSTRING_value(db->data, i); | |
d02b48c6 | 203 | |
0f113f3e MC |
204 | l = 0; |
205 | for (j = 0; j < nn; j++) { | |
206 | if (pp[j] != NULL) | |
207 | l += strlen(pp[j]); | |
208 | } | |
209 | if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn))) | |
210 | goto err; | |
d02b48c6 | 211 | |
0f113f3e MC |
212 | p = buf->data; |
213 | for (j = 0; j < nn; j++) { | |
214 | f = pp[j]; | |
215 | if (f != NULL) | |
216 | for (;;) { | |
217 | if (*f == '\0') | |
218 | break; | |
219 | if (*f == '\t') | |
220 | *(p++) = '\\'; | |
221 | *(p++) = *(f++); | |
222 | } | |
223 | *(p++) = '\t'; | |
224 | } | |
225 | p[-1] = '\n'; | |
226 | j = p - buf->data; | |
227 | if (BIO_write(out, buf->data, (int)j) != j) | |
228 | goto err; | |
229 | tot += j; | |
230 | } | |
231 | ret = tot; | |
232 | err: | |
25aaa98a | 233 | BUF_MEM_free(buf); |
0f113f3e MC |
234 | return (ret); |
235 | } | |
d02b48c6 | 236 | |
c869da88 | 237 | int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row) |
0f113f3e MC |
238 | { |
239 | int i; | |
240 | OPENSSL_STRING *r; | |
d02b48c6 | 241 | |
0f113f3e MC |
242 | for (i = 0; i < db->num_fields; i++) { |
243 | if (db->index[i] != NULL) { | |
244 | if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) | |
245 | continue; | |
246 | r = lh_OPENSSL_STRING_retrieve(db->index[i], row); | |
247 | if (r != NULL) { | |
248 | db->error = DB_ERROR_INDEX_CLASH; | |
249 | db->arg1 = i; | |
250 | db->arg_row = r; | |
251 | goto err; | |
252 | } | |
253 | } | |
254 | } | |
d02b48c6 | 255 | |
0f113f3e MC |
256 | for (i = 0; i < db->num_fields; i++) { |
257 | if (db->index[i] != NULL) { | |
258 | if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) | |
259 | continue; | |
260 | (void)lh_OPENSSL_STRING_insert(db->index[i], row); | |
9ad52c56 BE |
261 | if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL) |
262 | goto err1; | |
0f113f3e MC |
263 | } |
264 | } | |
9ad52c56 BE |
265 | if (!sk_OPENSSL_PSTRING_push(db->data, row)) |
266 | goto err1; | |
208fb891 | 267 | return 1; |
9ad52c56 BE |
268 | |
269 | err1: | |
270 | db->error = DB_ERROR_MALLOC; | |
271 | while (i-- > 0) { | |
272 | if (db->index[i] != NULL) { | |
273 | if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0)) | |
274 | continue; | |
275 | (void)lh_OPENSSL_STRING_delete(db->index[i], row); | |
276 | } | |
277 | } | |
0f113f3e MC |
278 | err: |
279 | return (0); | |
280 | } | |
d02b48c6 | 281 | |
6b691a5c | 282 | void TXT_DB_free(TXT_DB *db) |
0f113f3e MC |
283 | { |
284 | int i, n; | |
285 | char **p, *max; | |
d02b48c6 | 286 | |
0f113f3e MC |
287 | if (db == NULL) |
288 | return; | |
e03ddfae | 289 | |
0f113f3e MC |
290 | if (db->index != NULL) { |
291 | for (i = db->num_fields - 1; i >= 0; i--) | |
25aaa98a | 292 | lh_OPENSSL_STRING_free(db->index[i]); |
0f113f3e MC |
293 | OPENSSL_free(db->index); |
294 | } | |
b548a1f1 | 295 | OPENSSL_free(db->qual); |
0f113f3e MC |
296 | if (db->data != NULL) { |
297 | for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) { | |
298 | /* | |
299 | * check if any 'fields' have been allocated from outside of the | |
300 | * initial block | |
301 | */ | |
302 | p = sk_OPENSSL_PSTRING_value(db->data, i); | |
303 | max = p[db->num_fields]; /* last address */ | |
304 | if (max == NULL) { /* new row */ | |
305 | for (n = 0; n < db->num_fields; n++) | |
b548a1f1 | 306 | OPENSSL_free(p[n]); |
0f113f3e MC |
307 | } else { |
308 | for (n = 0; n < db->num_fields; n++) { | |
b548a1f1 | 309 | if (((p[n] < (char *)p) || (p[n] > max))) |
0f113f3e MC |
310 | OPENSSL_free(p[n]); |
311 | } | |
312 | } | |
313 | OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i)); | |
314 | } | |
315 | sk_OPENSSL_PSTRING_free(db->data); | |
316 | } | |
317 | OPENSSL_free(db); | |
318 | } |