txt_db.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright 1995-2023 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. #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. i = 0;
  76. f = buf->data;
  77. esc = 0;
  78. for (;;) {
  79. if (*f == '\0')
  80. break;
  81. if (*f == '\t') {
  82. if (esc)
  83. p--;
  84. else {
  85. *(p++) = '\0';
  86. f++;
  87. if (n >= num)
  88. break;
  89. pp[n++] = p;
  90. continue;
  91. }
  92. }
  93. esc = (*f == '\\');
  94. *(p++) = *(f++);
  95. }
  96. *(p++) = '\0';
  97. if ((n != num) || (*f != '\0')) {
  98. OPENSSL_free(pp);
  99. ret->error = DB_ERROR_WRONG_NUM_FIELDS;
  100. goto err;
  101. }
  102. pp[n] = p;
  103. if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) {
  104. OPENSSL_free(pp);
  105. goto err;
  106. }
  107. }
  108. BUF_MEM_free(buf);
  109. return ret;
  110. err:
  111. BUF_MEM_free(buf);
  112. if (ret != NULL) {
  113. sk_OPENSSL_PSTRING_free(ret->data);
  114. OPENSSL_free(ret->index);
  115. OPENSSL_free(ret->qual);
  116. OPENSSL_free(ret);
  117. }
  118. return NULL;
  119. }
  120. OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx,
  121. OPENSSL_STRING *value)
  122. {
  123. OPENSSL_STRING *ret;
  124. LHASH_OF(OPENSSL_STRING) *lh;
  125. if (idx >= db->num_fields) {
  126. db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
  127. return NULL;
  128. }
  129. lh = db->index[idx];
  130. if (lh == NULL) {
  131. db->error = DB_ERROR_NO_INDEX;
  132. return NULL;
  133. }
  134. ret = lh_OPENSSL_STRING_retrieve(lh, value);
  135. db->error = DB_ERROR_OK;
  136. return ret;
  137. }
  138. int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *),
  139. OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp)
  140. {
  141. LHASH_OF(OPENSSL_STRING) *idx;
  142. OPENSSL_STRING *r, *k;
  143. int i, n;
  144. if (field >= db->num_fields) {
  145. db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
  146. return 0;
  147. }
  148. /* FIXME: we lose type checking at this point */
  149. if ((idx = (LHASH_OF(OPENSSL_STRING) *)OPENSSL_LH_new(hash, cmp)) == NULL) {
  150. db->error = DB_ERROR_MALLOC;
  151. return 0;
  152. }
  153. n = sk_OPENSSL_PSTRING_num(db->data);
  154. for (i = 0; i < n; i++) {
  155. r = sk_OPENSSL_PSTRING_value(db->data, i);
  156. if ((qual != NULL) && (qual(r) == 0))
  157. continue;
  158. if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
  159. db->error = DB_ERROR_INDEX_CLASH;
  160. db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k);
  161. db->arg2 = i;
  162. lh_OPENSSL_STRING_free(idx);
  163. return 0;
  164. }
  165. if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) {
  166. db->error = DB_ERROR_MALLOC;
  167. lh_OPENSSL_STRING_free(idx);
  168. return 0;
  169. }
  170. }
  171. lh_OPENSSL_STRING_free(db->index[field]);
  172. db->index[field] = idx;
  173. db->qual[field] = qual;
  174. return 1;
  175. }
  176. long TXT_DB_write(BIO *out, TXT_DB *db)
  177. {
  178. long i, j, n, nn, l, tot = 0;
  179. char *p, **pp, *f;
  180. BUF_MEM *buf = NULL;
  181. long ret = -1;
  182. if ((buf = BUF_MEM_new()) == NULL)
  183. goto err;
  184. n = sk_OPENSSL_PSTRING_num(db->data);
  185. nn = db->num_fields;
  186. for (i = 0; i < n; i++) {
  187. pp = sk_OPENSSL_PSTRING_value(db->data, i);
  188. l = 0;
  189. for (j = 0; j < nn; j++) {
  190. if (pp[j] != NULL)
  191. l += strlen(pp[j]);
  192. }
  193. if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn)))
  194. goto err;
  195. p = buf->data;
  196. for (j = 0; j < nn; j++) {
  197. f = pp[j];
  198. if (f != NULL)
  199. for (;;) {
  200. if (*f == '\0')
  201. break;
  202. if (*f == '\t')
  203. *(p++) = '\\';
  204. *(p++) = *(f++);
  205. }
  206. *(p++) = '\t';
  207. }
  208. p[-1] = '\n';
  209. j = p - buf->data;
  210. if (BIO_write(out, buf->data, (int)j) != j)
  211. goto err;
  212. tot += j;
  213. }
  214. ret = tot;
  215. err:
  216. BUF_MEM_free(buf);
  217. return ret;
  218. }
  219. int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
  220. {
  221. int i;
  222. OPENSSL_STRING *r;
  223. for (i = 0; i < db->num_fields; i++) {
  224. if (db->index[i] != NULL) {
  225. if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
  226. continue;
  227. r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
  228. if (r != NULL) {
  229. db->error = DB_ERROR_INDEX_CLASH;
  230. db->arg1 = i;
  231. db->arg_row = r;
  232. goto err;
  233. }
  234. }
  235. }
  236. for (i = 0; i < db->num_fields; i++) {
  237. if (db->index[i] != NULL) {
  238. if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
  239. continue;
  240. (void)lh_OPENSSL_STRING_insert(db->index[i], row);
  241. if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL)
  242. goto err1;
  243. }
  244. }
  245. if (!sk_OPENSSL_PSTRING_push(db->data, row))
  246. goto err1;
  247. return 1;
  248. err1:
  249. db->error = DB_ERROR_MALLOC;
  250. while (i-- > 0) {
  251. if (db->index[i] != NULL) {
  252. if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
  253. continue;
  254. (void)lh_OPENSSL_STRING_delete(db->index[i], row);
  255. }
  256. }
  257. err:
  258. return 0;
  259. }
  260. void TXT_DB_free(TXT_DB *db)
  261. {
  262. int i, n;
  263. char **p, *max;
  264. if (db == NULL)
  265. return;
  266. if (db->index != NULL) {
  267. for (i = db->num_fields - 1; i >= 0; i--)
  268. lh_OPENSSL_STRING_free(db->index[i]);
  269. OPENSSL_free(db->index);
  270. }
  271. OPENSSL_free(db->qual);
  272. if (db->data != NULL) {
  273. for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
  274. /*
  275. * check if any 'fields' have been allocated from outside of the
  276. * initial block
  277. */
  278. p = sk_OPENSSL_PSTRING_value(db->data, i);
  279. max = p[db->num_fields]; /* last address */
  280. if (max == NULL) { /* new row */
  281. for (n = 0; n < db->num_fields; n++)
  282. OPENSSL_free(p[n]);
  283. } else {
  284. for (n = 0; n < db->num_fields; n++) {
  285. if (((p[n] < (char *)p) || (p[n] > max)))
  286. OPENSSL_free(p[n]);
  287. }
  288. }
  289. OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i));
  290. }
  291. sk_OPENSSL_PSTRING_free(db->data);
  292. }
  293. OPENSSL_free(db);
  294. }