blob: cf1198d10ee9e0d43ee0afc8645bb591f540b32a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/net/sunrpc/auth.c
3 *
4 * Generic RPC client authentication API.
5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */
8
9#include <linux/types.h>
10#include <linux/sched.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include <linux/errno.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#include <linux/sunrpc/clnt.h>
15#include <linux/spinlock.h>
16
17#ifdef RPC_DEBUG
18# define RPCDBG_FACILITY RPCDBG_AUTH
19#endif
20
Trond Myklebustfc1b3562007-06-09 16:15:46 -040021static DEFINE_SPINLOCK(rpc_authflavor_lock);
Trond Myklebustf1c0a862007-06-23 20:17:58 -040022static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070023 &authnull_ops, /* AUTH_NULL */
24 &authunix_ops, /* AUTH_UNIX */
25 NULL, /* others can be loadable modules */
26};
27
Trond Myklebuste092bdc2007-06-23 19:45:36 -040028static LIST_HEAD(cred_unused);
29
Linus Torvalds1da177e2005-04-16 15:20:36 -070030static u32
31pseudoflavor_to_flavor(u32 flavor) {
32 if (flavor >= RPC_AUTH_MAXFLAVOR)
33 return RPC_AUTH_GSS;
34 return flavor;
35}
36
37int
Trond Myklebustf1c0a862007-06-23 20:17:58 -040038rpcauth_register(const struct rpc_authops *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -070039{
40 rpc_authflavor_t flavor;
Trond Myklebustfc1b3562007-06-09 16:15:46 -040041 int ret = -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
43 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
44 return -EINVAL;
Trond Myklebustfc1b3562007-06-09 16:15:46 -040045 spin_lock(&rpc_authflavor_lock);
46 if (auth_flavors[flavor] == NULL) {
47 auth_flavors[flavor] = ops;
48 ret = 0;
49 }
50 spin_unlock(&rpc_authflavor_lock);
51 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052}
53
54int
Trond Myklebustf1c0a862007-06-23 20:17:58 -040055rpcauth_unregister(const struct rpc_authops *ops)
Linus Torvalds1da177e2005-04-16 15:20:36 -070056{
57 rpc_authflavor_t flavor;
Trond Myklebustfc1b3562007-06-09 16:15:46 -040058 int ret = -EPERM;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
61 return -EINVAL;
Trond Myklebustfc1b3562007-06-09 16:15:46 -040062 spin_lock(&rpc_authflavor_lock);
63 if (auth_flavors[flavor] == ops) {
64 auth_flavors[flavor] = NULL;
65 ret = 0;
66 }
67 spin_unlock(&rpc_authflavor_lock);
68 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -070069}
70
71struct rpc_auth *
72rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
73{
74 struct rpc_auth *auth;
Trond Myklebustf1c0a862007-06-23 20:17:58 -040075 const struct rpc_authops *ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
77
Olaf Kirchf344f6d2006-03-20 13:44:08 -050078 auth = ERR_PTR(-EINVAL);
79 if (flavor >= RPC_AUTH_MAXFLAVOR)
80 goto out;
81
Olaf Kirchf344f6d2006-03-20 13:44:08 -050082#ifdef CONFIG_KMOD
83 if ((ops = auth_flavors[flavor]) == NULL)
84 request_module("rpc-auth-%u", flavor);
85#endif
Trond Myklebustfc1b3562007-06-09 16:15:46 -040086 spin_lock(&rpc_authflavor_lock);
87 ops = auth_flavors[flavor];
88 if (ops == NULL || !try_module_get(ops->owner)) {
89 spin_unlock(&rpc_authflavor_lock);
Olaf Kirchf344f6d2006-03-20 13:44:08 -050090 goto out;
Trond Myklebustfc1b3562007-06-09 16:15:46 -040091 }
92 spin_unlock(&rpc_authflavor_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 auth = ops->create(clnt, pseudoflavor);
Trond Myklebustfc1b3562007-06-09 16:15:46 -040094 module_put(ops->owner);
J. Bruce Fields6a192752005-06-22 17:16:23 +000095 if (IS_ERR(auth))
96 return auth;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 if (clnt->cl_auth)
Trond Myklebustde7a8ce2007-06-23 10:46:47 -040098 rpcauth_release(clnt->cl_auth);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099 clnt->cl_auth = auth;
Olaf Kirchf344f6d2006-03-20 13:44:08 -0500100
101out:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 return auth;
103}
104
105void
Trond Myklebustde7a8ce2007-06-23 10:46:47 -0400106rpcauth_release(struct rpc_auth *auth)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107{
108 if (!atomic_dec_and_test(&auth->au_count))
109 return;
110 auth->au_ops->destroy(auth);
111}
112
113static DEFINE_SPINLOCK(rpc_credcache_lock);
114
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400115static void
116rpcauth_unhash_cred_locked(struct rpc_cred *cred)
117{
118 hlist_del_rcu(&cred->cr_hash);
119 smp_mb__before_clear_bit();
120 clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
121}
122
Trond Myklebust9499b432007-06-24 15:57:57 -0400123static void
124rpcauth_unhash_cred(struct rpc_cred *cred)
125{
126 spinlock_t *cache_lock;
127
128 cache_lock = &cred->cr_auth->au_credcache->lock;
129 spin_lock(cache_lock);
130 if (atomic_read(&cred->cr_count) == 0)
131 rpcauth_unhash_cred_locked(cred);
132 spin_unlock(cache_lock);
133}
134
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135/*
136 * Initialize RPC credential cache
137 */
138int
139rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
140{
141 struct rpc_cred_cache *new;
142 int i;
143
Kris Katterjohn8b3a7002006-01-11 15:56:43 -0800144 new = kmalloc(sizeof(*new), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 if (!new)
146 return -ENOMEM;
147 for (i = 0; i < RPC_CREDCACHE_NR; i++)
148 INIT_HLIST_HEAD(&new->hashtable[i]);
Trond Myklebust9499b432007-06-24 15:57:57 -0400149 spin_lock_init(&new->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 new->expire = expire;
151 new->nextgc = jiffies + (expire >> 1);
152 auth->au_credcache = new;
153 return 0;
154}
155
156/*
157 * Destroy a list of credentials
158 */
159static inline
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400160void rpcauth_destroy_credlist(struct list_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161{
162 struct rpc_cred *cred;
163
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400164 while (!list_empty(head)) {
165 cred = list_entry(head->next, struct rpc_cred, cr_lru);
166 list_del_init(&cred->cr_lru);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 put_rpccred(cred);
168 }
169}
170
171/*
172 * Clear the RPC credential cache, and delete those credentials
173 * that are not referenced.
174 */
175void
Trond Myklebust3ab9bb72007-06-09 15:41:42 -0400176rpcauth_clear_credcache(struct rpc_cred_cache *cache)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177{
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400178 LIST_HEAD(free);
179 struct hlist_head *head;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180 struct rpc_cred *cred;
181 int i;
182
183 spin_lock(&rpc_credcache_lock);
Trond Myklebust9499b432007-06-24 15:57:57 -0400184 spin_lock(&cache->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 for (i = 0; i < RPC_CREDCACHE_NR; i++) {
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400186 head = &cache->hashtable[i];
187 while (!hlist_empty(head)) {
188 cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
189 get_rpccred(cred);
190 list_move_tail(&cred->cr_lru, &free);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400191 rpcauth_unhash_cred_locked(cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 }
193 }
Trond Myklebust9499b432007-06-24 15:57:57 -0400194 spin_unlock(&cache->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 spin_unlock(&rpc_credcache_lock);
196 rpcauth_destroy_credlist(&free);
197}
198
Trond Myklebust3ab9bb72007-06-09 15:41:42 -0400199/*
200 * Destroy the RPC credential cache
201 */
202void
203rpcauth_destroy_credcache(struct rpc_auth *auth)
204{
205 struct rpc_cred_cache *cache = auth->au_credcache;
206
207 if (cache) {
208 auth->au_credcache = NULL;
209 rpcauth_clear_credcache(cache);
210 kfree(cache);
211 }
212}
213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214/*
215 * Remove stale credentials. Avoid sleeping inside the loop.
216 */
217static void
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400218rpcauth_prune_expired(struct list_head *free)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219{
Trond Myklebust9499b432007-06-24 15:57:57 -0400220 spinlock_t *cache_lock;
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400221 struct rpc_cred *cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400223 while (!list_empty(&cred_unused)) {
224 cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
225 if (time_after(jiffies, cred->cr_expire +
226 cred->cr_auth->au_credcache->expire))
227 break;
228 list_del_init(&cred->cr_lru);
229 if (atomic_read(&cred->cr_count) != 0)
230 continue;
Trond Myklebust9499b432007-06-24 15:57:57 -0400231 cache_lock = &cred->cr_auth->au_credcache->lock;
232 spin_lock(cache_lock);
233 if (atomic_read(&cred->cr_count) == 0) {
234 get_rpccred(cred);
235 list_add_tail(&cred->cr_lru, free);
236 rpcauth_unhash_cred_locked(cred);
237 }
238 spin_unlock(cache_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400240}
241
242/*
243 * Run garbage collector.
244 */
245static void
246rpcauth_gc_credcache(struct rpc_cred_cache *cache, struct list_head *free)
247{
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400248 if (list_empty(&cred_unused) || time_before(jiffies, cache->nextgc))
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400249 return;
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400250 spin_lock(&rpc_credcache_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251 cache->nextgc = jiffies + cache->expire;
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400252 rpcauth_prune_expired(free);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400253 spin_unlock(&rpc_credcache_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254}
255
256/*
257 * Look up a process' credentials in the authentication cache
258 */
259struct rpc_cred *
260rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
Trond Myklebust8a317762006-02-01 12:18:36 -0500261 int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262{
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400263 LIST_HEAD(free);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264 struct rpc_cred_cache *cache = auth->au_credcache;
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400265 struct hlist_node *pos;
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400266 struct rpc_cred *cred = NULL,
267 *entry, *new;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268 int nr = 0;
269
Trond Myklebust8a317762006-02-01 12:18:36 -0500270 if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 nr = acred->uid & RPC_CREDCACHE_MASK;
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400272
273 rcu_read_lock();
274 hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) {
275 if (!entry->cr_ops->crmatch(acred, entry, flags))
276 continue;
Trond Myklebust9499b432007-06-24 15:57:57 -0400277 spin_lock(&cache->lock);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400278 if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) {
Trond Myklebust9499b432007-06-24 15:57:57 -0400279 spin_unlock(&cache->lock);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400280 continue;
281 }
282 cred = get_rpccred(entry);
Trond Myklebust9499b432007-06-24 15:57:57 -0400283 spin_unlock(&cache->lock);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400284 break;
285 }
286 rcu_read_unlock();
287
Trond Myklebust9499b432007-06-24 15:57:57 -0400288 if (cred != NULL)
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400289 goto found;
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400290
291 new = auth->au_ops->crcreate(auth, acred, flags);
292 if (IS_ERR(new)) {
293 cred = new;
294 goto out;
295 }
296
Trond Myklebust9499b432007-06-24 15:57:57 -0400297 spin_lock(&cache->lock);
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400298 hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
299 if (!entry->cr_ops->crmatch(acred, entry, flags))
300 continue;
301 cred = get_rpccred(entry);
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400302 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 }
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400304 if (cred == NULL) {
Trond Myklebust5fe47552007-06-23 19:55:31 -0400305 cred = new;
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400306 set_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
307 hlist_add_head_rcu(&cred->cr_hash, &cache->hashtable[nr]);
308 } else
309 list_add_tail(&new->cr_lru, &free);
Trond Myklebust9499b432007-06-24 15:57:57 -0400310 spin_unlock(&cache->lock);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400311found:
312 if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
Trond Myklebustfba3bad2006-02-01 12:19:27 -0500313 && cred->cr_ops->cr_init != NULL
314 && !(flags & RPCAUTH_LOOKUP_NEW)) {
315 int res = cred->cr_ops->cr_init(auth, cred);
316 if (res < 0) {
317 put_rpccred(cred);
318 cred = ERR_PTR(res);
319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 }
Trond Myklebust9499b432007-06-24 15:57:57 -0400321 rpcauth_gc_credcache(cache, &free);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400322 rpcauth_destroy_credlist(&free);
323out:
324 return cred;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325}
326
327struct rpc_cred *
Trond Myklebust8a317762006-02-01 12:18:36 -0500328rpcauth_lookupcred(struct rpc_auth *auth, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329{
330 struct auth_cred acred = {
331 .uid = current->fsuid,
332 .gid = current->fsgid,
333 .group_info = current->group_info,
334 };
335 struct rpc_cred *ret;
336
Chuck Lever46121cf2007-01-31 12:14:08 -0500337 dprintk("RPC: looking up %s cred\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 auth->au_ops->au_name);
339 get_group_info(acred.group_info);
Trond Myklebust8a317762006-02-01 12:18:36 -0500340 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 put_group_info(acred.group_info);
342 return ret;
343}
344
Trond Myklebust5fe47552007-06-23 19:55:31 -0400345void
346rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
347 struct rpc_auth *auth, const struct rpc_credops *ops)
348{
349 INIT_HLIST_NODE(&cred->cr_hash);
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400350 INIT_LIST_HEAD(&cred->cr_lru);
Trond Myklebust5fe47552007-06-23 19:55:31 -0400351 atomic_set(&cred->cr_count, 1);
352 cred->cr_auth = auth;
353 cred->cr_ops = ops;
354 cred->cr_expire = jiffies;
355#ifdef RPC_DEBUG
356 cred->cr_magic = RPCAUTH_CRED_MAGIC;
357#endif
358 cred->cr_uid = acred->uid;
359}
360EXPORT_SYMBOL(rpcauth_init_cred);
361
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362struct rpc_cred *
363rpcauth_bindcred(struct rpc_task *task)
364{
365 struct rpc_auth *auth = task->tk_auth;
366 struct auth_cred acred = {
367 .uid = current->fsuid,
368 .gid = current->fsgid,
369 .group_info = current->group_info,
370 };
371 struct rpc_cred *ret;
Trond Myklebust8a317762006-02-01 12:18:36 -0500372 int flags = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Chuck Lever46121cf2007-01-31 12:14:08 -0500374 dprintk("RPC: %5u looking up %s cred\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 task->tk_pid, task->tk_auth->au_ops->au_name);
376 get_group_info(acred.group_info);
Trond Myklebust8a317762006-02-01 12:18:36 -0500377 if (task->tk_flags & RPC_TASK_ROOTCREDS)
378 flags |= RPCAUTH_LOOKUP_ROOTCREDS;
379 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 if (!IS_ERR(ret))
381 task->tk_msg.rpc_cred = ret;
382 else
383 task->tk_status = PTR_ERR(ret);
384 put_group_info(acred.group_info);
385 return ret;
386}
387
388void
389rpcauth_holdcred(struct rpc_task *task)
390{
Chuck Lever46121cf2007-01-31 12:14:08 -0500391 dprintk("RPC: %5u holding %s cred %p\n",
392 task->tk_pid, task->tk_auth->au_ops->au_name,
393 task->tk_msg.rpc_cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 if (task->tk_msg.rpc_cred)
395 get_rpccred(task->tk_msg.rpc_cred);
396}
397
398void
399put_rpccred(struct rpc_cred *cred)
400{
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400401 /* Fast path for unhashed credentials */
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400402 if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400403 goto need_lock;
404
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 if (!atomic_dec_and_test(&cred->cr_count))
406 return;
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400407 goto out_destroy;
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400408need_lock:
409 if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
410 return;
411 if (!list_empty(&cred->cr_lru))
412 list_del_init(&cred->cr_lru);
413 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
Trond Myklebust9499b432007-06-24 15:57:57 -0400414 rpcauth_unhash_cred(cred);
Trond Myklebust31be5bf2007-06-24 15:55:26 -0400415 else if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
Trond Myklebuste092bdc2007-06-23 19:45:36 -0400416 cred->cr_expire = jiffies;
417 list_add_tail(&cred->cr_lru, &cred_unused);
418 spin_unlock(&rpc_credcache_lock);
419 return;
420 }
421 spin_unlock(&rpc_credcache_lock);
422out_destroy:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 cred->cr_ops->crdestroy(cred);
424}
425
426void
427rpcauth_unbindcred(struct rpc_task *task)
428{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 struct rpc_cred *cred = task->tk_msg.rpc_cred;
430
Chuck Lever46121cf2007-01-31 12:14:08 -0500431 dprintk("RPC: %5u releasing %s cred %p\n",
Chuck Lever0bbacc42005-11-01 16:53:32 -0500432 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
434 put_rpccred(cred);
435 task->tk_msg.rpc_cred = NULL;
436}
437
Alexey Dobriyand8ed0292006-09-26 22:29:38 -0700438__be32 *
439rpcauth_marshcred(struct rpc_task *task, __be32 *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 struct rpc_cred *cred = task->tk_msg.rpc_cred;
442
Chuck Lever46121cf2007-01-31 12:14:08 -0500443 dprintk("RPC: %5u marshaling %s cred %p\n",
Chuck Lever0bbacc42005-11-01 16:53:32 -0500444 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
445
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446 return cred->cr_ops->crmarshal(task, p);
447}
448
Alexey Dobriyand8ed0292006-09-26 22:29:38 -0700449__be32 *
450rpcauth_checkverf(struct rpc_task *task, __be32 *p)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 struct rpc_cred *cred = task->tk_msg.rpc_cred;
453
Chuck Lever46121cf2007-01-31 12:14:08 -0500454 dprintk("RPC: %5u validating %s cred %p\n",
Chuck Lever0bbacc42005-11-01 16:53:32 -0500455 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
456
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 return cred->cr_ops->crvalidate(task, p);
458}
459
460int
461rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
Alexey Dobriyand8ed0292006-09-26 22:29:38 -0700462 __be32 *data, void *obj)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
464 struct rpc_cred *cred = task->tk_msg.rpc_cred;
465
Chuck Lever46121cf2007-01-31 12:14:08 -0500466 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 task->tk_pid, cred->cr_ops->cr_name, cred);
468 if (cred->cr_ops->crwrap_req)
469 return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
470 /* By default, we encode the arguments normally. */
471 return encode(rqstp, data, obj);
472}
473
474int
475rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
Alexey Dobriyand8ed0292006-09-26 22:29:38 -0700476 __be32 *data, void *obj)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477{
478 struct rpc_cred *cred = task->tk_msg.rpc_cred;
479
Chuck Lever46121cf2007-01-31 12:14:08 -0500480 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 task->tk_pid, cred->cr_ops->cr_name, cred);
482 if (cred->cr_ops->crunwrap_resp)
483 return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
484 data, obj);
485 /* By default, we decode the arguments normally. */
486 return decode(rqstp, data, obj);
487}
488
489int
490rpcauth_refreshcred(struct rpc_task *task)
491{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 struct rpc_cred *cred = task->tk_msg.rpc_cred;
493 int err;
494
Chuck Lever46121cf2007-01-31 12:14:08 -0500495 dprintk("RPC: %5u refreshing %s cred %p\n",
Chuck Lever0bbacc42005-11-01 16:53:32 -0500496 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
497
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 err = cred->cr_ops->crrefresh(task);
499 if (err < 0)
500 task->tk_status = err;
501 return err;
502}
503
504void
505rpcauth_invalcred(struct rpc_task *task)
506{
Trond Myklebustfc432dd2007-06-25 10:15:15 -0400507 struct rpc_cred *cred = task->tk_msg.rpc_cred;
508
Chuck Lever46121cf2007-01-31 12:14:08 -0500509 dprintk("RPC: %5u invalidating %s cred %p\n",
Trond Myklebustfc432dd2007-06-25 10:15:15 -0400510 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
511 if (cred)
512 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513}
514
515int
516rpcauth_uptodatecred(struct rpc_task *task)
517{
Trond Myklebustfc432dd2007-06-25 10:15:15 -0400518 struct rpc_cred *cred = task->tk_msg.rpc_cred;
519
520 return cred == NULL ||
521 test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522}