/* General persistent per-UID keyrings register
 *
 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public Licence
 * as published by the Free Software Foundation; either version
 * 2 of the Licence, or (at your option) any later version.
 */

#include <linux/user_namespace.h>
#include "internal.h"

unsigned persistent_keyring_expiry = 3 * 24 * 3600; /* Expire after 3 days of non-use */

/*
 * Create the persistent keyring register for the current user namespace.
 *
 * Called with the namespace's sem locked for writing.
 */
static int key_create_persistent_register(struct user_namespace *ns)
{
	struct key *reg = keyring_alloc(".persistent_register",
					KUIDT_INIT(0), KGIDT_INIT(0),
					current_cred(),
					((KEY_POS_ALL & ~KEY_POS_SETATTR) |
					 KEY_USR_VIEW | KEY_USR_READ),
					KEY_ALLOC_NOT_IN_QUOTA, NULL);
	if (IS_ERR(reg))
		return PTR_ERR(reg);

	ns->persistent_keyring_register = reg;
	return 0;
}

/*
 * Create the persistent keyring for the specified user.
 *
 * Called with the namespace's sem locked for writing.
 */
static key_ref_t key_create_persistent(struct user_namespace *ns, kuid_t uid,
				       struct keyring_index_key *index_key)
{
	struct key *persistent;
	key_ref_t reg_ref, persistent_ref;

	if (!ns->persistent_keyring_register) {
		long err = key_create_persistent_register(ns);
		if (err < 0)
			return ERR_PTR(err);
	} else {
		reg_ref = make_key_ref(ns->persistent_keyring_register, true);
		persistent_ref = find_key_to_update(reg_ref, index_key);
		if (persistent_ref)
			return persistent_ref;
	}

	persistent = keyring_alloc(index_key->description,
				   uid, INVALID_GID, current_cred(),
				   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
				    KEY_USR_VIEW | KEY_USR_READ),
				   KEY_ALLOC_NOT_IN_QUOTA,
				   ns->persistent_keyring_register);
	if (IS_ERR(persistent))
		return ERR_CAST(persistent);

	return make_key_ref(persistent, true);
}

/*
 * Get the persistent keyring for a specific UID and link it to the nominated
 * keyring.
 */
static long key_get_persistent(struct user_namespace *ns, kuid_t uid,
			       key_ref_t dest_ref)
{
	struct keyring_index_key index_key;
	struct key *persistent;
	key_ref_t reg_ref, persistent_ref;
	char buf[32];
	long ret;

	/* Look in the register if it exists */
	index_key.type = &key_type_keyring;
	index_key.description = buf;
	index_key.desc_len = sprintf(buf, "_persistent.%u", from_kuid(ns, uid));

	if (ns->persistent_keyring_register) {
		reg_ref = make_key_ref(ns->persistent_keyring_register, true);
		down_read(&ns->persistent_keyring_register_sem);
		persistent_ref = find_key_to_update(reg_ref, &index_key);
		up_read(&ns->persistent_keyring_register_sem);

		if (persistent_ref)
			goto found;
	}

	/* It wasn't in the register, so we'll need to create it.  We might
	 * also need to create the register.
	 */
	down_write(&ns->persistent_keyring_register_sem);
	persistent_ref = key_create_persistent(ns, uid, &index_key);
	up_write(&ns->persistent_keyring_register_sem);
	if (!IS_ERR(persistent_ref))
		goto found;

	return PTR_ERR(persistent_ref);

found:
	ret = key_task_permission(persistent_ref, current_cred(), KEY_NEED_LINK);
	if (ret == 0) {
		persistent = key_ref_to_ptr(persistent_ref);
		ret = key_link(key_ref_to_ptr(dest_ref), persistent);
		if (ret == 0) {
			key_set_timeout(persistent, persistent_keyring_expiry);
			ret = persistent->serial;		
		}
	}

	key_ref_put(persistent_ref);
	return ret;
}

/*
 * Get the persistent keyring for a specific UID and link it to the nominated
 * keyring.
 */
long keyctl_get_persistent(uid_t _uid, key_serial_t destid)
{
	struct user_namespace *ns = current_user_ns();
	key_ref_t dest_ref;
	kuid_t uid;
	long ret;

	/* -1 indicates the current user */
	if (_uid == (uid_t)-1) {
		uid = current_uid();
	} else {
		uid = make_kuid(ns, _uid);
		if (!uid_valid(uid))
			return -EINVAL;

		/* You can only see your own persistent cache if you're not
		 * sufficiently privileged.
		 */
		if (!uid_eq(uid, current_uid()) &&
		    !uid_eq(uid, current_euid()) &&
		    !ns_capable(ns, CAP_SETUID))
			return -EPERM;
	}

	/* There must be a destination keyring */
	dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
	if (IS_ERR(dest_ref))
		return PTR_ERR(dest_ref);
	if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) {
		ret = -ENOTDIR;
		goto out_put_dest;
	}

	ret = key_get_persistent(ns, uid, dest_ref);

out_put_dest:
	key_ref_put(dest_ref);
	return ret;
}
