2 * linux/net/sunrpc/auth.c
4 * Generic RPC client authentication API.
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
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>
14 #include <linux/sunrpc/clnt.h>
15 #include <linux/spinlock.h>
18 # define RPCDBG_FACILITY RPCDBG_AUTH
21 static DEFINE_SPINLOCK(rpc_authflavor_lock);
22 static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
23 &authnull_ops, /* AUTH_NULL */
24 &authunix_ops, /* AUTH_UNIX */
25 NULL, /* others can be loadable modules */
28 static LIST_HEAD(cred_unused);
31 pseudoflavor_to_flavor(u32 flavor) {
32 if (flavor >= RPC_AUTH_MAXFLAVOR)
38 rpcauth_register(const struct rpc_authops *ops)
40 rpc_authflavor_t flavor;
43 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
45 spin_lock(&rpc_authflavor_lock);
46 if (auth_flavors[flavor] == NULL) {
47 auth_flavors[flavor] = ops;
50 spin_unlock(&rpc_authflavor_lock);
55 rpcauth_unregister(const struct rpc_authops *ops)
57 rpc_authflavor_t flavor;
60 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
62 spin_lock(&rpc_authflavor_lock);
63 if (auth_flavors[flavor] == ops) {
64 auth_flavors[flavor] = NULL;
67 spin_unlock(&rpc_authflavor_lock);
72 rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
74 struct rpc_auth *auth;
75 const struct rpc_authops *ops;
76 u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
78 auth = ERR_PTR(-EINVAL);
79 if (flavor >= RPC_AUTH_MAXFLAVOR)
83 if ((ops = auth_flavors[flavor]) == NULL)
84 request_module("rpc-auth-%u", flavor);
86 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);
92 spin_unlock(&rpc_authflavor_lock);
93 auth = ops->create(clnt, pseudoflavor);
94 module_put(ops->owner);
98 rpcauth_release(clnt->cl_auth);
106 rpcauth_release(struct rpc_auth *auth)
108 if (!atomic_dec_and_test(&auth->au_count))
110 auth->au_ops->destroy(auth);
113 static DEFINE_SPINLOCK(rpc_credcache_lock);
116 * Initialize RPC credential cache
119 rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
121 struct rpc_cred_cache *new;
124 new = kmalloc(sizeof(*new), GFP_KERNEL);
127 for (i = 0; i < RPC_CREDCACHE_NR; i++)
128 INIT_HLIST_HEAD(&new->hashtable[i]);
129 new->expire = expire;
130 new->nextgc = jiffies + (expire >> 1);
131 auth->au_credcache = new;
136 * Destroy a list of credentials
139 void rpcauth_destroy_credlist(struct list_head *head)
141 struct rpc_cred *cred;
143 while (!list_empty(head)) {
144 cred = list_entry(head->next, struct rpc_cred, cr_lru);
145 list_del_init(&cred->cr_lru);
151 * Clear the RPC credential cache, and delete those credentials
152 * that are not referenced.
155 rpcauth_clear_credcache(struct rpc_cred_cache *cache)
158 struct hlist_head *head;
159 struct rpc_cred *cred;
162 spin_lock(&rpc_credcache_lock);
163 for (i = 0; i < RPC_CREDCACHE_NR; i++) {
164 head = &cache->hashtable[i];
165 while (!hlist_empty(head)) {
166 cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
168 list_move_tail(&cred->cr_lru, &free);
170 hlist_del_init(&cred->cr_hash);
173 spin_unlock(&rpc_credcache_lock);
174 rpcauth_destroy_credlist(&free);
178 * Destroy the RPC credential cache
181 rpcauth_destroy_credcache(struct rpc_auth *auth)
183 struct rpc_cred_cache *cache = auth->au_credcache;
186 auth->au_credcache = NULL;
187 rpcauth_clear_credcache(cache);
193 * Remove stale credentials. Avoid sleeping inside the loop.
196 rpcauth_prune_expired(struct list_head *free)
198 struct rpc_cred *cred;
200 while (!list_empty(&cred_unused)) {
201 cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
202 if (time_after(jiffies, cred->cr_expire +
203 cred->cr_auth->au_credcache->expire))
205 list_del_init(&cred->cr_lru);
206 if (atomic_read(&cred->cr_count) != 0)
209 list_add_tail(&cred->cr_lru, free);
211 hlist_del_init(&cred->cr_hash);
216 * Run garbage collector.
219 rpcauth_gc_credcache(struct rpc_cred_cache *cache, struct list_head *free)
221 if (time_before(jiffies, cache->nextgc))
223 cache->nextgc = jiffies + cache->expire;
224 rpcauth_prune_expired(free);
228 * Look up a process' credentials in the authentication cache
231 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
235 struct rpc_cred_cache *cache = auth->au_credcache;
236 struct hlist_node *pos;
237 struct rpc_cred *new = NULL,
242 if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
243 nr = acred->uid & RPC_CREDCACHE_MASK;
245 spin_lock(&rpc_credcache_lock);
246 hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
247 if (!entry->cr_ops->crmatch(acred, entry, flags))
249 cred = get_rpccred(entry);
250 hlist_del(&entry->cr_hash);
255 list_add_tail(&new->cr_lru, &free);
260 hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
262 rpcauth_gc_credcache(cache, &free);
263 spin_unlock(&rpc_credcache_lock);
265 rpcauth_destroy_credlist(&free);
268 new = auth->au_ops->crcreate(auth, acred, flags);
272 } else if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
273 && cred->cr_ops->cr_init != NULL
274 && !(flags & RPCAUTH_LOOKUP_NEW)) {
275 int res = cred->cr_ops->cr_init(auth, cred);
282 return (struct rpc_cred *) cred;
286 rpcauth_lookupcred(struct rpc_auth *auth, int flags)
288 struct auth_cred acred = {
289 .uid = current->fsuid,
290 .gid = current->fsgid,
291 .group_info = current->group_info,
293 struct rpc_cred *ret;
295 dprintk("RPC: looking up %s cred\n",
296 auth->au_ops->au_name);
297 get_group_info(acred.group_info);
298 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
299 put_group_info(acred.group_info);
304 rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
305 struct rpc_auth *auth, const struct rpc_credops *ops)
307 INIT_HLIST_NODE(&cred->cr_hash);
308 INIT_LIST_HEAD(&cred->cr_lru);
309 atomic_set(&cred->cr_count, 1);
310 cred->cr_auth = auth;
312 cred->cr_expire = jiffies;
314 cred->cr_magic = RPCAUTH_CRED_MAGIC;
316 cred->cr_uid = acred->uid;
318 EXPORT_SYMBOL(rpcauth_init_cred);
321 rpcauth_bindcred(struct rpc_task *task)
323 struct rpc_auth *auth = task->tk_auth;
324 struct auth_cred acred = {
325 .uid = current->fsuid,
326 .gid = current->fsgid,
327 .group_info = current->group_info,
329 struct rpc_cred *ret;
332 dprintk("RPC: %5u looking up %s cred\n",
333 task->tk_pid, task->tk_auth->au_ops->au_name);
334 get_group_info(acred.group_info);
335 if (task->tk_flags & RPC_TASK_ROOTCREDS)
336 flags |= RPCAUTH_LOOKUP_ROOTCREDS;
337 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
339 task->tk_msg.rpc_cred = ret;
341 task->tk_status = PTR_ERR(ret);
342 put_group_info(acred.group_info);
347 rpcauth_holdcred(struct rpc_task *task)
349 dprintk("RPC: %5u holding %s cred %p\n",
350 task->tk_pid, task->tk_auth->au_ops->au_name,
351 task->tk_msg.rpc_cred);
352 if (task->tk_msg.rpc_cred)
353 get_rpccred(task->tk_msg.rpc_cred);
357 put_rpccred(struct rpc_cred *cred)
359 /* Fast path for unhashed credentials */
360 if (!hlist_unhashed(&cred->cr_hash))
363 if (!atomic_dec_and_test(&cred->cr_count))
368 if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
370 if (!list_empty(&cred->cr_lru))
371 list_del_init(&cred->cr_lru);
372 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
373 hlist_del(&cred->cr_hash);
374 else if (!hlist_unhashed(&cred->cr_hash)) {
375 cred->cr_expire = jiffies;
376 list_add_tail(&cred->cr_lru, &cred_unused);
377 spin_unlock(&rpc_credcache_lock);
380 spin_unlock(&rpc_credcache_lock);
382 cred->cr_ops->crdestroy(cred);
386 rpcauth_unbindcred(struct rpc_task *task)
388 struct rpc_cred *cred = task->tk_msg.rpc_cred;
390 dprintk("RPC: %5u releasing %s cred %p\n",
391 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
394 task->tk_msg.rpc_cred = NULL;
398 rpcauth_marshcred(struct rpc_task *task, __be32 *p)
400 struct rpc_cred *cred = task->tk_msg.rpc_cred;
402 dprintk("RPC: %5u marshaling %s cred %p\n",
403 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
405 return cred->cr_ops->crmarshal(task, p);
409 rpcauth_checkverf(struct rpc_task *task, __be32 *p)
411 struct rpc_cred *cred = task->tk_msg.rpc_cred;
413 dprintk("RPC: %5u validating %s cred %p\n",
414 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
416 return cred->cr_ops->crvalidate(task, p);
420 rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
421 __be32 *data, void *obj)
423 struct rpc_cred *cred = task->tk_msg.rpc_cred;
425 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
426 task->tk_pid, cred->cr_ops->cr_name, cred);
427 if (cred->cr_ops->crwrap_req)
428 return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
429 /* By default, we encode the arguments normally. */
430 return encode(rqstp, data, obj);
434 rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
435 __be32 *data, void *obj)
437 struct rpc_cred *cred = task->tk_msg.rpc_cred;
439 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
440 task->tk_pid, cred->cr_ops->cr_name, cred);
441 if (cred->cr_ops->crunwrap_resp)
442 return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
444 /* By default, we decode the arguments normally. */
445 return decode(rqstp, data, obj);
449 rpcauth_refreshcred(struct rpc_task *task)
451 struct rpc_cred *cred = task->tk_msg.rpc_cred;
454 dprintk("RPC: %5u refreshing %s cred %p\n",
455 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
457 err = cred->cr_ops->crrefresh(task);
459 task->tk_status = err;
464 rpcauth_invalcred(struct rpc_task *task)
466 struct rpc_cred *cred = task->tk_msg.rpc_cred;
468 dprintk("RPC: %5u invalidating %s cred %p\n",
469 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
471 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
475 rpcauth_uptodatecred(struct rpc_task *task)
477 struct rpc_cred *cred = task->tk_msg.rpc_cred;
479 return cred == NULL ||
480 test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0;