diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-12 12:24:49 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-14 13:42:38 -0400 |
commit | 9a559efd4199c9812d339e23cc1b6055366b224f (patch) | |
tree | 44ae54434a6bd368693ea76b210448496e222e46 /net/sunrpc/auth_generic.c | |
parent | 4ccda2cdd8d156b6f49440653d5d6997e0facf97 (diff) |
SUNRPC: Add a generic RPC credential
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>
Diffstat (limited to 'net/sunrpc/auth_generic.c')
-rw-r--r-- | net/sunrpc/auth_generic.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c new file mode 100644 index 000000000000..6f129b1b20a0 --- /dev/null +++ b/net/sunrpc/auth_generic.c | |||
@@ -0,0 +1,142 @@ | |||
1 | /* | ||
2 | * Generic RPC credential | ||
3 | * | ||
4 | * Copyright (C) 2008, Trond Myklebust <Trond.Myklebust@netapp.com> | ||
5 | */ | ||
6 | |||
7 | #include <linux/err.h> | ||
8 | #include <linux/types.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/sunrpc/auth.h> | ||
12 | #include <linux/sunrpc/clnt.h> | ||
13 | #include <linux/sunrpc/debug.h> | ||
14 | #include <linux/sunrpc/sched.h> | ||
15 | |||
16 | #ifdef RPC_DEBUG | ||
17 | # define RPCDBG_FACILITY RPCDBG_AUTH | ||
18 | #endif | ||
19 | |||
20 | struct generic_cred { | ||
21 | struct rpc_cred gc_base; | ||
22 | struct auth_cred acred; | ||
23 | }; | ||
24 | |||
25 | static struct rpc_auth generic_auth; | ||
26 | static struct rpc_cred_cache generic_cred_cache; | ||
27 | static const struct rpc_credops generic_credops; | ||
28 | |||
29 | /* | ||
30 | * Public call interface | ||
31 | */ | ||
32 | struct rpc_cred *rpc_lookup_cred(void) | ||
33 | { | ||
34 | return rpcauth_lookupcred(&generic_auth, 0); | ||
35 | } | ||
36 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); | ||
37 | |||
38 | /* | ||
39 | * Lookup generic creds for current process | ||
40 | */ | ||
41 | static struct rpc_cred * | ||
42 | generic_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | ||
43 | { | ||
44 | return rpcauth_lookup_credcache(&generic_auth, acred, flags); | ||
45 | } | ||
46 | |||
47 | static struct rpc_cred * | ||
48 | generic_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | ||
49 | { | ||
50 | struct generic_cred *gcred; | ||
51 | |||
52 | gcred = kmalloc(sizeof(*gcred), GFP_KERNEL); | ||
53 | if (gcred == NULL) | ||
54 | return ERR_PTR(-ENOMEM); | ||
55 | |||
56 | rpcauth_init_cred(&gcred->gc_base, acred, &generic_auth, &generic_credops); | ||
57 | gcred->gc_base.cr_flags = 1UL << RPCAUTH_CRED_UPTODATE; | ||
58 | |||
59 | gcred->acred.uid = acred->uid; | ||
60 | gcred->acred.gid = acred->gid; | ||
61 | gcred->acred.group_info = acred->group_info; | ||
62 | if (gcred->acred.group_info != NULL) | ||
63 | get_group_info(gcred->acred.group_info); | ||
64 | |||
65 | dprintk("RPC: allocated generic cred %p for uid %d gid %d\n", | ||
66 | gcred, acred->uid, acred->gid); | ||
67 | return &gcred->gc_base; | ||
68 | } | ||
69 | |||
70 | static void | ||
71 | generic_free_cred(struct rpc_cred *cred) | ||
72 | { | ||
73 | struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); | ||
74 | |||
75 | dprintk("RPC: generic_free_cred %p\n", gcred); | ||
76 | if (gcred->acred.group_info != NULL) | ||
77 | put_group_info(gcred->acred.group_info); | ||
78 | kfree(gcred); | ||
79 | } | ||
80 | |||
81 | static void | ||
82 | generic_free_cred_callback(struct rcu_head *head) | ||
83 | { | ||
84 | struct rpc_cred *cred = container_of(head, struct rpc_cred, cr_rcu); | ||
85 | generic_free_cred(cred); | ||
86 | } | ||
87 | |||
88 | static void | ||
89 | generic_destroy_cred(struct rpc_cred *cred) | ||
90 | { | ||
91 | call_rcu(&cred->cr_rcu, generic_free_cred_callback); | ||
92 | } | ||
93 | |||
94 | /* | ||
95 | * Match credentials against current process creds. | ||
96 | */ | ||
97 | static int | ||
98 | generic_match(struct auth_cred *acred, struct rpc_cred *cred, int flags) | ||
99 | { | ||
100 | struct generic_cred *gcred = container_of(cred, struct generic_cred, gc_base); | ||
101 | |||
102 | if (gcred->acred.uid != acred->uid || | ||
103 | gcred->acred.gid != acred->gid || | ||
104 | gcred->acred.group_info != acred->group_info) | ||
105 | return 0; | ||
106 | return 1; | ||
107 | } | ||
108 | |||
109 | void __init rpc_init_generic_auth(void) | ||
110 | { | ||
111 | spin_lock_init(&generic_cred_cache.lock); | ||
112 | } | ||
113 | |||
114 | void __exit rpc_destroy_generic_auth(void) | ||
115 | { | ||
116 | rpcauth_clear_credcache(&generic_cred_cache); | ||
117 | } | ||
118 | |||
119 | static struct rpc_cred_cache generic_cred_cache = { | ||
120 | {{ NULL, },}, | ||
121 | }; | ||
122 | |||
123 | static const struct rpc_authops generic_auth_ops = { | ||
124 | .owner = THIS_MODULE, | ||
125 | #ifdef RPC_DEBUG | ||
126 | .au_name = "Generic", | ||
127 | #endif | ||
128 | .lookup_cred = generic_lookup_cred, | ||
129 | .crcreate = generic_create_cred, | ||
130 | }; | ||
131 | |||
132 | static struct rpc_auth generic_auth = { | ||
133 | .au_ops = &generic_auth_ops, | ||
134 | .au_count = ATOMIC_INIT(0), | ||
135 | .au_credcache = &generic_cred_cache, | ||
136 | }; | ||
137 | |||
138 | static const struct rpc_credops generic_credops = { | ||
139 | .cr_name = "Generic cred", | ||
140 | .crdestroy = generic_destroy_cred, | ||
141 | .crmatch = generic_match, | ||
142 | }; | ||