A local copy of OpenSSL from GitHub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

301 lines
8.0 KiB

  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. #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. long ln = 0;
  22. int i, add, n;
  23. int size = BUFSIZE;
  24. int offset = 0;
  25. char *p, *f;
  26. OPENSSL_STRING *pp;
  27. BUF_MEM *buf = NULL;
  28. if ((buf = BUF_MEM_new()) == NULL)
  29. goto err;
  30. if (!BUF_MEM_grow(buf, size))
  31. goto err;
  32. if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
  33. goto err;
  34. ret->num_fields = num;
  35. ret->index = NULL;
  36. ret->qual = NULL;
  37. if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL)
  38. goto err;
  39. if ((ret->index = OPENSSL_malloc(sizeof(*ret->index) * num)) == NULL)
  40. goto err;
  41. if ((ret->qual = OPENSSL_malloc(sizeof(*(ret->qual)) * num)) == NULL)
  42. goto err;
  43. for (i = 0; i < num; i++) {
  44. ret->index[i] = NULL;
  45. ret->qual[i] = NULL;
  46. }
  47. add = (num + 1) * sizeof(char *);
  48. buf->data[size - 1] = '\0';
  49. offset = 0;
  50. for (;;) {
  51. if (offset != 0) {
  52. size += BUFSIZE;
  53. if (!BUF_MEM_grow_clean(buf, size))
  54. goto err;
  55. }
  56. buf->data[offset] = '\0';
  57. BIO_gets(in, &(buf->data[offset]), size - offset);
  58. ln++;
  59. if (buf->data[offset] == '\0')
  60. break;
  61. if ((offset == 0) && (buf->data[0] == '#'))
  62. continue;
  63. i = strlen(&(buf->data[offset]));
  64. offset += i;
  65. if (buf->data[offset - 1] != '\n')
  66. continue;
  67. else {
  68. buf->data[offset - 1] = '\0'; /* blat the '\n' */
  69. if ((p = OPENSSL_malloc(add + offset)) == NULL)
  70. goto err;
  71. offset = 0;
  72. }
  73. pp = (char **)p;
  74. p += add;
  75. n = 0;
  76. pp[n++] = p;
  77. i = 0;
  78. f = buf->data;
  79. esc = 0;
  80. for (;;) {
  81. if (*f == '\0')
  82. break;
  83. if (*f == '\t') {
  84. if (esc)
  85. p--;
  86. else {
  87. *(p++) = '\0';
  88. f++;
  89. if (n >= num)
  90. break;
  91. pp[n++] = p;
  92. continue;
  93. }
  94. }
  95. esc = (*f == '\\');
  96. *(p++) = *(f++);
  97. }
  98. *(p++) = '\0';
  99. if ((n != num) || (*f != '\0')) {
  100. ret->error = DB_ERROR_WRONG_NUM_FIELDS;
  101. goto err;
  102. }
  103. pp[n] = p;
  104. if (!sk_OPENSSL_PSTRING_push(ret->data, pp))
  105. goto err;
  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. LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
  139. {
  140. LHASH_OF(OPENSSL_STRING) *idx;
  141. OPENSSL_STRING *r;
  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) *)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 ((r = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
  158. db->error = DB_ERROR_INDEX_CLASH;
  159. db->arg1 = sk_OPENSSL_PSTRING_find(db->data, r);
  160. db->arg2 = i;
  161. lh_OPENSSL_STRING_free(idx);
  162. return (0);
  163. }
  164. }
  165. lh_OPENSSL_STRING_free(db->index[field]);
  166. db->index[field] = idx;
  167. db->qual[field] = qual;
  168. return (1);
  169. }
  170. long TXT_DB_write(BIO *out, TXT_DB *db)
  171. {
  172. long i, j, n, nn, l, tot = 0;
  173. char *p, **pp, *f;
  174. BUF_MEM *buf = NULL;
  175. long ret = -1;
  176. if ((buf = BUF_MEM_new()) == NULL)
  177. goto err;
  178. n = sk_OPENSSL_PSTRING_num(db->data);
  179. nn = db->num_fields;
  180. for (i = 0; i < n; i++) {
  181. pp = sk_OPENSSL_PSTRING_value(db->data, i);
  182. l = 0;
  183. for (j = 0; j < nn; j++) {
  184. if (pp[j] != NULL)
  185. l += strlen(pp[j]);
  186. }
  187. if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn)))
  188. goto err;
  189. p = buf->data;
  190. for (j = 0; j < nn; j++) {
  191. f = pp[j];
  192. if (f != NULL)
  193. for (;;) {
  194. if (*f == '\0')
  195. break;
  196. if (*f == '\t')
  197. *(p++) = '\\';
  198. *(p++) = *(f++);
  199. }
  200. *(p++) = '\t';
  201. }
  202. p[-1] = '\n';
  203. j = p - buf->data;
  204. if (BIO_write(out, buf->data, (int)j) != j)
  205. goto err;
  206. tot += j;
  207. }
  208. ret = tot;
  209. err:
  210. BUF_MEM_free(buf);
  211. return (ret);
  212. }
  213. int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
  214. {
  215. int i;
  216. OPENSSL_STRING *r;
  217. for (i = 0; i < db->num_fields; i++) {
  218. if (db->index[i] != NULL) {
  219. if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
  220. continue;
  221. r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
  222. if (r != NULL) {
  223. db->error = DB_ERROR_INDEX_CLASH;
  224. db->arg1 = i;
  225. db->arg_row = r;
  226. goto err;
  227. }
  228. }
  229. }
  230. /* We have passed the index checks, now just append and insert */
  231. if (!sk_OPENSSL_PSTRING_push(db->data, row)) {
  232. db->error = DB_ERROR_MALLOC;
  233. goto err;
  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. }
  241. }
  242. return (1);
  243. err:
  244. return (0);
  245. }
  246. void TXT_DB_free(TXT_DB *db)
  247. {
  248. int i, n;
  249. char **p, *max;
  250. if (db == NULL)
  251. return;
  252. if (db->index != NULL) {
  253. for (i = db->num_fields - 1; i >= 0; i--)
  254. lh_OPENSSL_STRING_free(db->index[i]);
  255. OPENSSL_free(db->index);
  256. }
  257. OPENSSL_free(db->qual);
  258. if (db->data != NULL) {
  259. for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
  260. /*
  261. * check if any 'fields' have been allocated from outside of the
  262. * initial block
  263. */
  264. p = sk_OPENSSL_PSTRING_value(db->data, i);
  265. max = p[db->num_fields]; /* last address */
  266. if (max == NULL) { /* new row */
  267. for (n = 0; n < db->num_fields; n++)
  268. OPENSSL_free(p[n]);
  269. } else {
  270. for (n = 0; n < db->num_fields; n++) {
  271. if (((p[n] < (char *)p) || (p[n] > max)))
  272. OPENSSL_free(p[n]);
  273. }
  274. }
  275. OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i));
  276. }
  277. sk_OPENSSL_PSTRING_free(db->data);
  278. }
  279. OPENSSL_free(db);
  280. }