/*
 * This file is part of the UCB release of Plan 9. It is subject to the license
 * terms in the LICENSE file found in the top-level directory of this
 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
 * part of the UCB release of Plan 9, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms contained
 * in the LICENSE file.
 */

#include <slab.h>
#include <kmalloc.h>
#include <kref.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <error.h>
#include <cpio.h>
#include <pmap.h>
#include <smp.h>
#include <net/ip.h>

#include <crypto/2crypto.h>
#include <crypto/2hmac.h>
#include <crypto/2id.h>
#include <crypto/2sha.h>

#include <ctype.h>

enum {
	Hashlen = VB2_MAX_DIGEST_SIZE * 2,
	Maxhash = 256,
};

/*
 *  if a process knows cap->cap, it can change user
 *  to capabilty->user.
 */
struct Caphash {
	struct Caphash *next;
	char hash[Hashlen + 1];
};

struct {
	qlock_t qlock;
	struct Caphash *first;
	int nhash;
} capalloc;

enum {
	Qdir,
	Qhash,
	Quse,
};

/* caphash must be last */
struct dirtab capdir[] = {
	{".",       {Qdir, 0, QTDIR}, 0, DMDIR | 0500},
	{"capuse",  {Quse},           0, 0222,},
	{"caphash", {Qhash},          0, 0200,},
};
int ncapdir = ARRAY_SIZE(capdir);

static void capinit(void)
{
	qlock_init(&capalloc.qlock);
}

static struct chan *capattach(char *spec)
{
	return devattach("capability", spec);
}

static struct walkqid *capwalk(struct chan *c, struct chan *nc, char **name,
                               unsigned int nname)
{
	return devwalk(c, nc, name, nname, capdir, ncapdir, devgen);
}

static void capremove(struct chan *c)
{
	if (iseve() && c->qid.path == Qhash)
		ncapdir = ARRAY_SIZE(capdir) - 1;
	else
		error(EPERM, "Permission denied");
}

static size_t capstat(struct chan *c, uint8_t *db, size_t n)
{
	return devstat(c, db, n, capdir, ncapdir, devgen);
}

/*
 *  if the stream doesn't exist, create it
 */
static struct chan *capopen(struct chan *c, int omode)
{
	if (c->qid.type & QTDIR) {
		if (openmode(omode) != O_READ)
			error(EISDIR, "Can only read a directory");
		c->mode = openmode(omode);
		c->flag |= COPEN;
		c->offset = 0;
		return c;
	}

	switch ((uint32_t)c->qid.path) {
	case Qhash:
		if (!iseve())
			error(EPERM,
			      "Permission denied: only eve can open Qhash");
		break;
	}

	c->mode = openmode(omode);
	c->flag |= COPEN;
	c->offset = 0;
	return c;
}

static size_t __hashstr(char *buf, uint8_t *hash, size_t bytes_to_split)
{
	int i;

	for (i = 0; i < bytes_to_split; i++)
		snprintf(buf + 2 * i, 3, "%02x", hash[i]);

	return bytes_to_split;
}

static struct Caphash *remcap(uint8_t *hash)
{
	struct Caphash *t, **l;

	qlock(&capalloc.qlock);

	/* find the matching capability */
	for (l = &capalloc.first; *l != NULL;) {
		t = *l;
		if (memcmp(hash, t->hash, Hashlen) == 0)
			break;
		l = &t->next;
	}
	t = *l;
	if (t != NULL) {
		capalloc.nhash--;
		*l = t->next;
	}
	qunlock(&capalloc.qlock);

	return t;
}

/* add a capability, throwing out any old ones */
static void addcap(uint8_t *hash)
{
	struct Caphash *p, *t, **l;

	p = kzmalloc(sizeof(*p), MEM_WAIT);
	memmove(p->hash, hash, Hashlen);
	p->next = NULL;

	qlock(&capalloc.qlock);

	/* trim extras */
	while (capalloc.nhash >= Maxhash) {
		t = capalloc.first;
		if (t == NULL)
			panic("addcap");
		capalloc.first = t->next;
		kfree(t);
		capalloc.nhash--;
	}

	/* add new one */
	for (l = &capalloc.first; *l != NULL; l = &(*l)->next)
		;
	*l = p;
	capalloc.nhash++;

	qunlock(&capalloc.qlock);
}

static void capclose(struct chan *c)
{
}

static size_t capread(struct chan *c, void *va, size_t n, off64_t m)
{
	switch ((uint32_t)c->qid.path) {
	case Qdir:
		return devdirread(c, va, n, capdir, ncapdir, devgen);

	default:
		error(EPERM, "Permission denied: can't read capability files");
		break;
	}
	return n;
}

static size_t capwrite(struct chan *c, void *va, size_t n, off64_t m)
{
	struct Caphash *p;
	char *cp, *hashstr;
	uint8_t hash[Hashlen + 1] = {0};
	char *key, *from, *to;
	int ret;
	ERRSTACK(1);

	switch ((uint32_t)c->qid.path) {
	case Qhash:
		if (!iseve())
			error(EPERM, "permission denied: you must be eve");
		if (n < VB2_SHA256_DIGEST_SIZE * 2)
			error(EIO, "Short read: on Qhash");
		memmove(hash, va, Hashlen);
		for (int i = 0; i < Hashlen; i++)
			hash[i] = tolower(hash[i]);
		addcap(hash);
		break;

	case Quse:
		/* copy key to avoid a fault in hmac_xx and so we can enforce
		 * null termination. */
		cp = kzmalloc(n + 1, MEM_WAIT);
		hashstr = kzmalloc(sizeof(hash), MEM_WAIT);
		if (waserror()) {
			kfree(cp);
			kfree(hashstr);
			nexterror();
		}
		memmove(cp, va, n);
		cp[n] = 0;

		from = cp;
		key = strrchr(cp, '@');
		if (key == NULL)
			error(EIO, "short read: Quse");
		*key++ = 0;

		ret = hmac(VB2_HASH_SHA256, key, strlen(key),
		           from, strlen(from), hash, Hashlen);
		if (ret)
			error(EINVAL, "HMAC failed");

		// Convert to ASCII text
		ret = __hashstr(hashstr, hash, VB2_SHA256_DIGEST_SIZE);
		if (ret != VB2_SHA256_DIGEST_SIZE)
			error(EINVAL, "hash is wrong length");

		p = remcap((uint8_t *)hashstr);
		if (p == NULL)
			error(EINVAL, "invalid capability %s@%s", from, key);
		kfree(p);

		/* if a from user is supplied, make sure it matches */
		to = strchr(from, '@');
		if (to == NULL) {
			to = from;
		} else {
			*to++ = 0;
			if (strcmp(from, current->user.name) != 0)
				error(EINVAL, "capability must match user");
		}

		/* set user id */
		// In the original user names were NULL-terminated; ensure
		// that is still the case.
		if (strlen(to) > sizeof(current->user.name) - 1)
			error(EINVAL, "New user name is > %d bytes",
			      sizeof(current->user.name) - 1);
		proc_set_username(current, to);
		//up->basepri = PriNormal;

		kfree(cp);
		kfree(hashstr);
		poperror();
		break;

	default:
		error(EPERM, "permission denied: capwrite");
		break;
	}

	return n;
}

struct dev capdevtab __devtab = {
	.name = "capability",

	.reset = devreset,
	.init = capinit,
	.shutdown = devshutdown,
	.attach = capattach,
	.walk = capwalk,
	.stat = capstat,
	.open = capopen,
	.create = devcreate,
	.close = capclose,
	.read = capread,
	.bread = devbread,
	.write = capwrite,
	.bwrite = devbwrite,
	.remove = capremove,
	.wstat = devwstat,
};
