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