/*
 * Simple memory cache for ini file parser
 *
 *  This should be copied from somewhere but, unfortunately is reinvented.
 *
 * Copyright (C) 2019 James.Bottomley@HansenPartnership.com
 *
 * SPDX-License-Identifier: LGPL-2.1-only
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include "openssl-pkcs11.h"

struct kv {
	const char *key;
	const char *value;
	int len;
};

struct s_s {
	const char *section;
	struct kv *kvs;
	int kv_count;
};


static struct s_s *s = NULL;
static int section_count = 0;

static struct s_s *section_get(const char *section)
{
	int i;

	for (i = 0; i < section_count; i++)
		if (strcmp(s[i].section, section) == 0)
			return &s[i];
	return NULL;
}

static void remove_section(int sn)
{
	section_count--;
	/* last entry, just keep the reduced count (realloc will cope) */
	if (sn == section_count) {
		return;
	}

	/* just move everything over it and reduce the section count */
	memcpy(&s[sn], &s[sn + 1], sizeof(struct s_s)*(section_count - sn));
}

static struct s_s *section_get_alloc(const char *section)
{
	struct s_s *s_s = section_get(section);

	if (s_s)
		return s_s;
	s = reallocarray(s, section_count + 1, sizeof(*s_s));
	if (!s) {
		fprintf(stderr, "realloc of section %s failed: %s",
			section, strerror(errno));
		return NULL;
	}
	s_s = &s[section_count++];
	memset(s_s, 0, sizeof(*s_s));
	s_s->section = section;
	return s_s;
}

static struct kv *kv_get(struct s_s *s_s, const char *key)
{
	int i;

	for (i = 0; i < s_s->kv_count; i++)
		if (strcmp(s_s->kvs[i].key, key) == 0)
			return &s_s->kvs[i];
	return NULL;
}

static struct kv *kv_get_alloc(struct s_s *s_s, const char *key)
{
	struct kv *kv = kv_get(s_s, key);

	if (kv)
		return kv;

	s_s->kvs = reallocarray(s_s->kvs, s_s->kv_count + 1, sizeof(*kv));
		if (!s) {
		fprintf(stderr, "realloc of section %s kvs failed: %s",
			s_s->section, strerror(errno));
		return NULL;
	}
	kv = &s_s->kvs[s_s->kv_count++];
	memset(kv, 0, sizeof(*kv));
	kv->key = key;
	return kv;
}

static void cache_add_internal(struct s_s *s_s, const char *key,
			       const char *value, int len)
{
	struct kv *kv = kv_get_alloc(s_s, key);
	if (!kv)
		return;
	if (kv->value && kv->len == CACHE_PKEY)
		/* discard const */
		crypto_cache_free_pkey((void *)kv->value);
	if (len == 0)
		len = strlen(value);

	kv->value = value;
	kv->len = len;
}

void cache_add(const char *section, const char *key, const char *value, int len)
{
	struct s_s *s_s = section_get_alloc(section);

	if (!s_s)
		return;
	cache_add_internal(s_s, key, value, len);
}

void cache_add_by_secnum(int sec_num, const char *key, const char *value,
			 int len)
{
	struct s_s *s_s;

	if (sec_num > section_count)
		return;

	s_s = &s[sec_num];

	cache_add_internal(s_s, key, value, len);
}

static const char *
cache_get_internal(struct s_s *sec, const char *key, int *len)
{
	struct kv *kv;

	kv = kv_get(sec, key);

	if (!kv)
		return NULL;
	if (len)
		*len = kv->len;
	return kv->value;
}

const char *cache_get(const char *section, const char *key, int *len)
{
	struct s_s *sec = section_get(section);

	if (!sec)
		return NULL;

	return cache_get_internal(sec, key, len);
}

const char *cache_get_by_secnum(int sec_num, const char *key, int *len)
{
	struct s_s *sec;

	if (sec_num >= section_count)
		return NULL;
	sec = &s[sec_num];

	return cache_get_internal(sec, key, len);
}

const char *cache_get_section(int sc)
{
	if (sc >= section_count)
		return NULL;
	return s[sc].section;
}

int cache_get_sections(void)
{
	return section_count;
}

void cache_load_crypto_keys(void)
{
	int i;

	/* every section apart from global must have public key and  a
	 * private key */
	for (i = 1; i < section_count; i++) {
		struct kv *kv;

		kv = kv_get(&s[i], INI_PUBLIC_KEY);
		if (!kv) {
			kv = kv_get(&s[i], INI_CERT);
			if (kv)
				crypto_load_cert(i, kv->value);
		} else {
			crypto_load_public_key(i, kv->value);
		}
		if (!kv) {
			fprintf(stderr, "key '%s' has no '%s' or '%s' value\n",
				s[i].section, INI_PUBLIC_KEY, INI_CERT);
			/*
			 * a bit nasty, but removing the section
			 * in-place means we have to do over the value
			 * of i we just used
			 */
			remove_section(i--);
			continue;
		}
	}
}
