]> err.no Git - linux-2.6/blob - net/sunrpc/auth_generic.c
SUNRPC: Add a generic RPC credential
[linux-2.6] / net / sunrpc / auth_generic.c
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 };