]>
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')) { | |
51b04a61 | 107 | ret->error = DB_ERROR_WRONG_NUM_FIELDS; |
0f113f3e MC |
108 | goto err; |
109 | } | |
110 | pp[n] = p; | |
25aaa98a | 111 | if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) |
0f113f3e | 112 | goto err; |
0f113f3e | 113 | } |
25aaa98a RS |
114 | BUF_MEM_free(buf); |
115 | return ret; | |
0f113f3e MC |
116 | err: |
117 | BUF_MEM_free(buf); | |
25aaa98a RS |
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); | |
0f113f3e | 125 | } |
d02b48c6 | 126 | |
0f113f3e MC |
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; | |
d02b48c6 | 132 | |
0f113f3e MC |
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 | } | |
d02b48c6 | 146 | |
0f113f3e MC |
147 | int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *), |
148 | LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp) | |
149 | { | |
150 | LHASH_OF(OPENSSL_STRING) *idx; | |
151 | OPENSSL_STRING *r; | |
152 | int i, n; | |
d02b48c6 | 153 | |
0f113f3e MC |
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) *)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 | } | |
25aaa98a | 176 | lh_OPENSSL_STRING_free(db->index[field]); |
0f113f3e MC |
177 | db->index[field] = idx; |
178 | db->qual[field] = qual; | |
179 | return (1); | |
180 | } | |
d02b48c6 | 181 | |
6b691a5c | 182 | long TXT_DB_write(BIO *out, TXT_DB *db) |
0f113f3e MC |
183 | { |
184 | long i, j, n, nn, l, tot = 0; | |
185 | char *p, **pp, *f; | |
186 | BUF_MEM *buf = NULL; | |
187 | long ret = -1; | |
d02b48c6 | 188 | |
0f113f3e MC |
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); | |
d02b48c6 | 195 | |
0f113f3e MC |
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; | |
d02b48c6 | 203 | |
0f113f3e MC |
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: | |
25aaa98a | 225 | BUF_MEM_free(buf); |
0f113f3e MC |
226 | return (ret); |
227 | } | |
d02b48c6 | 228 | |
c869da88 | 229 | int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row) |
0f113f3e MC |
230 | { |
231 | int i; | |
232 | OPENSSL_STRING *r; | |
d02b48c6 | 233 | |
0f113f3e MC |
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 | } | |
d02b48c6 | 252 | |
0f113f3e MC |
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 | } | |
d02b48c6 | 264 | |
6b691a5c | 265 | void TXT_DB_free(TXT_DB *db) |
0f113f3e MC |
266 | { |
267 | int i, n; | |
268 | char **p, *max; | |
d02b48c6 | 269 | |
0f113f3e MC |
270 | if (db == NULL) |
271 | return; | |
e03ddfae | 272 | |
0f113f3e MC |
273 | if (db->index != NULL) { |
274 | for (i = db->num_fields - 1; i >= 0; i--) | |
25aaa98a | 275 | lh_OPENSSL_STRING_free(db->index[i]); |
0f113f3e MC |
276 | OPENSSL_free(db->index); |
277 | } | |
b548a1f1 | 278 | OPENSSL_free(db->qual); |
0f113f3e MC |
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++) | |
b548a1f1 | 289 | OPENSSL_free(p[n]); |
0f113f3e MC |
290 | } else { |
291 | for (n = 0; n < db->num_fields; n++) { | |
b548a1f1 | 292 | if (((p[n] < (char *)p) || (p[n] > max))) |
0f113f3e MC |
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 | } |