txt_db.c 8.4 KB

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