Skip to content

Commit

Permalink
SUNRPC: Add a generic RPC credential
Browse files Browse the repository at this point in the history
Add an rpc credential that is not tied to any particular auth mechanism,
but that can be cached by NFS, and later used to look up a cred for
whichever auth mechanism that turns out to be valid when the RPC call is
being made.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Mar 14, 2008
1 parent 4ccda2c commit 9a559ef
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 1 deletion.
3 changes: 3 additions & 0 deletions include/linux/sunrpc/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,12 @@ extern const struct rpc_authops authunix_ops;
extern const struct rpc_authops authnull_ops;

void __init rpc_init_authunix(void);
void __init rpc_init_generic_auth(void);
void __init rpcauth_init_module(void);
void __exit rpcauth_remove_module(void);
void __exit rpc_destroy_generic_auth(void);

struct rpc_cred * rpc_lookup_cred(void);
int rpcauth_register(const struct rpc_authops *);
int rpcauth_unregister(const struct rpc_authops *);
struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
Expand Down
2 changes: 1 addition & 1 deletion net/sunrpc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_gss/
obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/

sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \
auth.o auth_null.o auth_unix.o \
auth.o auth_null.o auth_unix.o auth_generic.o \
svc.o svcsock.o svcauth.o svcauth_unix.o \
rpcb_clnt.o timer.o xdr.o \
sunrpc_syms.o cache.o rpc_pipe.o \
Expand Down
1 change: 1 addition & 0 deletions net/sunrpc/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,7 @@ static struct shrinker rpc_cred_shrinker = {
void __init rpcauth_init_module(void)
{
rpc_init_authunix();
rpc_init_generic_auth();
register_shrinker(&rpc_cred_shrinker);
}

Expand Down
142 changes: 142 additions & 0 deletions net/sunrpc/auth_generic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Generic RPC credential
*
* Copyright (C) 2008, Trond Myklebust <Trond.Myklebust@netapp.com>
*/

#include <linux/err.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

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

static struct rpc_auth generic_auth;
static struct rpc_cred_cache generic_cred_cache;
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);

/*
* 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;
if (gcred->acred.group_info != NULL)
get_group_info(gcred->acred.group_info);

dprintk("RPC: allocated generic cred %p for uid %d gid %d\n",
gcred, acred->uid, 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);
}

/*
* 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);

if (gcred->acred.uid != acred->uid ||
gcred->acred.gid != acred->gid ||
gcred->acred.group_info != acred->group_info)
return 0;
return 1;
}

void __init rpc_init_generic_auth(void)
{
spin_lock_init(&generic_cred_cache.lock);
}

void __exit rpc_destroy_generic_auth(void)
{
rpcauth_clear_credcache(&generic_cred_cache);
}

static struct rpc_cred_cache generic_cred_cache = {
{{ NULL, },},
};

static const struct rpc_authops generic_auth_ops = {
.owner = THIS_MODULE,
#ifdef RPC_DEBUG
.au_name = "Generic",
#endif
.lookup_cred = generic_lookup_cred,
.crcreate = generic_create_cred,
};

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

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

0 comments on commit 9a559ef

Please sign in to comment.