/*
 * Generic RPC credential
 *
 * Copyright (C) 2008, Trond Myklebust <Trond.Myklebust@netapp.com>
 */

#include <linux/err.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/sunrpc/auth.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/debug.h>
#include <linux/sunrpc/sched.h>

#ifdef RPC_DEBUG
# define RPCDBG_FACILITY	RPCDBG_AUTH
#endif

#define RPC_MACHINE_CRED_USERID		GLOBAL_ROOT_UID
#define RPC_MACHINE_CRED_GROUPID	GLOBAL_ROOT_GID

struct generic_cred {
	struct rpc_cred gc_base;
	struct auth_cred acred;
};

static struct rpc_auth generic_auth;
static const struct rpc_credops generic_credops;

/*
 * Public call interface
 */
struct rpc_cred *rpc_lookup_cred(void)
{
	return rpcauth_lookupcred(&generic_auth, 0);
}
EXPORT_SYMBOL_GPL(rpc_lookup_cred);

struct rpc_cred *rpc_lookup_cred_nonblock(void)
{
	return rpcauth_lookupcred(&generic_auth, RPCAUTH_LOOKUP_RCU);
}
EXPORT_SYMBOL_GPL(rpc_lookup_cred_nonblock);

/*
 * Public call interface for looking up machine creds.
 */
struct rpc_cred *rpc_lookup_machine_cred(const char *service_name)
{
	struct auth_cred acred = {
		.uid = RPC_MACHINE_CRED_USERID,
		.gid = RPC_MACHINE_CRED_GROUPID,
		.principal = service_name,
		.machine_cred = 1,
	};

	dprintk("RPC:       looking up machine cred for service %s\n",
			service_name);
	return generic_auth.au_ops->lookup_cred(&generic_auth, &acred, 0);
}
EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred);

static struct rpc_cred *generic_bind_cred(struct rpc_task *task,
		struct rpc_cred *cred, int lookupflags)
{
	struct rpc_auth *auth = task->tk_client->cl_auth;
	struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred;

	return auth->au_ops->lookup_cred(auth, acred, lookupflags);
}

/*
 * Lookup generic creds for current process
 */
static struct rpc_cred *
generic_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
	return rpcauth_lookup_credcache(&generic_auth, acred, flags);
}

static struct rpc_cred *
generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
	struct generic_cred *gcred;

	gcred = kmalloc(sizeof(*gcred), GFP_KERNEL);
	if (gcred == NULL)
		return ERR_PTR(-ENOMEM);

	rpcauth_init_cred(&gcred->gc_base, acred, &generic_auth, &generic_credops);
	gcred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE;

	gcred->acred.uid = acred->uid;
	gcred->acred.gid = acred->gid;
	gcred->acred.group_info = acred->group_info;
	gcred->acred.ac_flags = 0;
	if (gcred->acred.group_info != NULL)
		get_group_info(gcred->acred.group_info);
	gcred->acred.machine_cred = acred->machine_cred;
	gcred->acred.principal = acred->principal;

	dprintk("RPC:       allocated %s cred %p for uid %d gid %d\n",
			gcred->acred.machine_cred ? "machine" : "generic",
			gcred,
			from_kuid(&init_user_ns, acred->uid),
			from_kgid(&init_user_ns, acred->gid));
	return &gcred->gc_base;
}

static void
generic_free_cred(struct rpc_cred *cred)
{
	struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);

	dprintk("RPC:       generic_free_cred %p\n", gcred);
	if (gcred->acred.group_info != NULL)
		put_group_info(gcred->acred.group_info);
	kfree(gcred);
}

static void
generic_free_cred_callback(struct rcu_head *head)
{
	struct rpc_cred *cred = container_of(head, struct rpc_cred, cr_rcu);
	generic_free_cred(cred);
}

static void
generic_destroy_cred(struct rpc_cred *cred)
{
	call_rcu(&cred->cr_rcu, generic_free_cred_callback);
}

static int
machine_cred_match(struct auth_cred *acred, struct generic_cred *gcred, int flags)
{
	if (!gcred->acred.machine_cred ||
	    gcred->acred.principal != acred->principal ||
	    !uid_eq(gcred->acred.uid, acred->uid) ||
	    !gid_eq(gcred->acred.gid, acred->gid))
		return 0;
	return 1;
}

/*
 * Match credentials against current process creds.
 */
static int
generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags)
{
	struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base);
	int i;

	if (acred->machine_cred)
		return machine_cred_match(acred, gcred, flags);

	if (!uid_eq(gcred->acred.uid, acred->uid) ||
	    !gid_eq(gcred->acred.gid, acred->gid) ||
	    gcred->acred.machine_cred != 0)
		goto out_nomatch;

	/* Optimisation in the case where pointers are identical... */
	if (gcred->acred.group_info == acred->group_info)
		goto out_match;

	/* Slow path... */
	if (gcred->acred.group_info->ngroups != acred->group_info->ngroups)
		goto out_nomatch;
	for (i = 0; i < gcred->acred.group_info->ngroups; i++) {
		if (!gid_eq(GROUP_AT(gcred->acred.group_info, i),
				GROUP_AT(acred->group_info, i)))
			goto out_nomatch;
	}
out_match:
	return 1;
out_nomatch:
	return 0;
}

int __init rpc_init_generic_auth(void)
{
	return rpcauth_init_credcache(&generic_auth);
}

void rpc_destroy_generic_auth(void)
{
	rpcauth_destroy_credcache(&generic_auth);
}

/*
 * Test the the current time (now) against the underlying credential key expiry
 * minus a timeout and setup notification.
 *
 * The normal case:
 * If 'now' is before the key expiry minus RPC_KEY_EXPIRE_TIMEO, set
 * the RPC_CRED_NOTIFY_TIMEOUT flag to setup the underlying credential
 * rpc_credops crmatch routine to notify this generic cred when it's key
 * expiration is within RPC_KEY_EXPIRE_TIMEO, and return 0.
 *
 * The error case:
 * If the underlying cred lookup fails, return -EACCES.
 *
 * The 'almost' error case:
 * If 'now' is within key expiry minus RPC_KEY_EXPIRE_TIMEO, but not within
 * key expiry minus RPC_KEY_EXPIRE_FAIL, set the RPC_CRED_EXPIRE_SOON bit
 * on the acred ac_flags and return 0.
 */
static int
generic_key_timeout(struct rpc_auth *auth, struct rpc_cred *cred)
{
	struct auth_cred *acred = &container_of(cred, struct generic_cred,
						gc_base)->acred;
	struct rpc_cred *tcred;
	int ret = 0;


	/* Fast track for non crkey_timeout (no key) underlying credentials */
	if (test_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags))
		return 0;

	/* Fast track for the normal case */
	if (test_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags))
		return 0;

	/* lookup_cred either returns a valid referenced rpc_cred, or PTR_ERR */
	tcred = auth->au_ops->lookup_cred(auth, acred, 0);
	if (IS_ERR(tcred))
		return -EACCES;

	if (!tcred->cr_ops->crkey_timeout) {
		set_bit(RPC_CRED_NO_CRKEY_TIMEOUT, &acred->ac_flags);
		ret = 0;
		goto out_put;
	}

	/* Test for the almost error case */
	ret = tcred->cr_ops->crkey_timeout(tcred);
	if (ret != 0) {
		set_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags);
		ret = 0;
	} else {
		/* In case underlying cred key has been reset */
		if (test_and_clear_bit(RPC_CRED_KEY_EXPIRE_SOON,
					&acred->ac_flags))
			dprintk("RPC:        UID %d Credential key reset\n",
				from_kuid(&init_user_ns, tcred->cr_uid));
		/* set up fasttrack for the normal case */
		set_bit(RPC_CRED_NOTIFY_TIMEOUT, &acred->ac_flags);
	}

out_put:
	put_rpccred(tcred);
	return ret;
}

static const struct rpc_authops generic_auth_ops = {
	.owner = THIS_MODULE,
	.au_name = "Generic",
	.lookup_cred = generic_lookup_cred,
	.crcreate = generic_create_cred,
	.key_timeout = generic_key_timeout,
};

static struct rpc_auth generic_auth = {
	.au_ops = &generic_auth_ops,
	.au_count = ATOMIC_INIT(0),
};

static bool generic_key_to_expire(struct rpc_cred *cred)
{
	struct auth_cred *acred = &container_of(cred, struct generic_cred,
						gc_base)->acred;
	bool ret;

	get_rpccred(cred);
	ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags);
	put_rpccred(cred);

	return ret;
}

static const struct rpc_credops generic_credops = {
	.cr_name = "Generic cred",
	.crdestroy = generic_destroy_cred,
	.crbind = generic_bind_cred,
	.crmatch = generic_match,
	.crkey_to_expire = generic_key_to_expire,
};
