~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/net/sunrpc/auth.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * linux/fs/nfs/rpcauth.c
  3  *
  4  * Generic RPC 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/malloc.h>
 12 #include <linux/errno.h>
 13 #include <linux/socket.h>
 14 #include <linux/sunrpc/clnt.h>
 15 #include <linux/spinlock.h>
 16 
 17 #ifdef RPC_DEBUG
 18 # define RPCDBG_FACILITY        RPCDBG_AUTH
 19 #endif
 20 
 21 #define RPC_MAXFLAVOR   8
 22 
 23 static struct rpc_authops *     auth_flavors[RPC_MAXFLAVOR] = {
 24         &authnull_ops,          /* AUTH_NULL */
 25         &authunix_ops,          /* AUTH_UNIX */
 26         NULL,                   /* others can be loadable modules */
 27 };
 28 
 29 int
 30 rpcauth_register(struct rpc_authops *ops)
 31 {
 32         unsigned int    flavor;
 33 
 34         if ((flavor = ops->au_flavor) >= RPC_MAXFLAVOR)
 35                 return -EINVAL;
 36         if (auth_flavors[flavor] != NULL)
 37                 return -EPERM;          /* what else? */
 38         auth_flavors[flavor] = ops;
 39         return 0;
 40 }
 41 
 42 int
 43 rpcauth_unregister(struct rpc_authops *ops)
 44 {
 45         unsigned int    flavor;
 46 
 47         if ((flavor = ops->au_flavor) >= RPC_MAXFLAVOR)
 48                 return -EINVAL;
 49         if (auth_flavors[flavor] != ops)
 50                 return -EPERM;          /* what else? */
 51         auth_flavors[flavor] = NULL;
 52         return 0;
 53 }
 54 
 55 struct rpc_auth *
 56 rpcauth_create(unsigned int flavor, struct rpc_clnt *clnt)
 57 {
 58         struct rpc_authops      *ops;
 59 
 60         if (flavor >= RPC_MAXFLAVOR || !(ops = auth_flavors[flavor]))
 61                 return NULL;
 62         clnt->cl_auth = ops->create(clnt);
 63         return clnt->cl_auth;
 64 }
 65 
 66 void
 67 rpcauth_destroy(struct rpc_auth *auth)
 68 {
 69         auth->au_ops->destroy(auth);
 70 }
 71 
 72 spinlock_t rpc_credcache_lock = SPIN_LOCK_UNLOCKED;
 73 
 74 /*
 75  * Initialize RPC credential cache
 76  */
 77 void
 78 rpcauth_init_credcache(struct rpc_auth *auth)
 79 {
 80         memset(auth->au_credcache, 0, sizeof(auth->au_credcache));
 81         auth->au_nextgc = jiffies + (auth->au_expire >> 1);
 82 }
 83 
 84 static inline void
 85 rpcauth_crdestroy(struct rpc_auth *auth, struct rpc_cred *cred)
 86 {
 87 #ifdef RPC_DEBUG
 88         if (cred->cr_magic != RPCAUTH_CRED_MAGIC)
 89                 BUG();
 90         cred->cr_magic = 0;
 91 #endif
 92         if (auth->au_ops->crdestroy)
 93                 auth->au_ops->crdestroy(cred);
 94         else
 95                 rpc_free(cred);
 96 }
 97 
 98 /*
 99  * Clear the RPC credential cache
100  */
101 void
102 rpcauth_free_credcache(struct rpc_auth *auth)
103 {
104         struct rpc_cred **q, *cred;
105         void            (*destroy)(struct rpc_cred *);
106         int             i;
107 
108         if (!(destroy = auth->au_ops->crdestroy))
109                 destroy = (void (*)(struct rpc_cred *)) rpc_free;
110 
111         spin_lock(&rpc_credcache_lock);
112         for (i = 0; i < RPC_CREDCACHE_NR; i++) {
113                 q = &auth->au_credcache[i];
114                 while ((cred = *q) != NULL) {
115                         *q = cred->cr_next;
116                         destroy(cred);
117                 }
118         }
119         spin_unlock(&rpc_credcache_lock);
120 }
121 
122 /*
123  * Remove stale credentials. Avoid sleeping inside the loop.
124  */
125 static void
126 rpcauth_gc_credcache(struct rpc_auth *auth)
127 {
128         struct rpc_cred **q, *cred, *free = NULL;
129         int             i;
130 
131         dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
132         spin_lock(&rpc_credcache_lock);
133         for (i = 0; i < RPC_CREDCACHE_NR; i++) {
134                 q = &auth->au_credcache[i];
135                 while ((cred = *q) != NULL) {
136                         if (!cred->cr_count &&
137                             time_before(cred->cr_expire, jiffies)) {
138                                 *q = cred->cr_next;
139                                 cred->cr_next = free;
140                                 free = cred;
141                                 continue;
142                         }
143                         q = &cred->cr_next;
144                 }
145         }
146         spin_unlock(&rpc_credcache_lock);
147         while ((cred = free) != NULL) {
148                 free = cred->cr_next;
149                 rpcauth_crdestroy(auth, cred);
150         }
151         auth->au_nextgc = jiffies + auth->au_expire;
152 }
153 
154 /*
155  * Insert credential into cache
156  */
157 void
158 rpcauth_insert_credcache(struct rpc_auth *auth, struct rpc_cred *cred)
159 {
160         int             nr;
161 
162         nr = (cred->cr_uid & RPC_CREDCACHE_MASK);
163         spin_lock(&rpc_credcache_lock);
164         cred->cr_next = auth->au_credcache[nr];
165         auth->au_credcache[nr] = cred;
166         cred->cr_count++;
167         cred->cr_expire = jiffies + auth->au_expire;
168         spin_unlock(&rpc_credcache_lock);
169 }
170 
171 /*
172  * Look up a process' credentials in the authentication cache
173  */
174 static struct rpc_cred *
175 rpcauth_lookup_credcache(struct rpc_auth *auth, int taskflags)
176 {
177         struct rpc_cred **q, *cred = NULL;
178         int             nr = 0;
179 
180         if (!(taskflags & RPC_TASK_ROOTCREDS))
181                 nr = current->uid & RPC_CREDCACHE_MASK;
182 
183         if (time_before(auth->au_nextgc, jiffies))
184                 rpcauth_gc_credcache(auth);
185 
186         spin_lock(&rpc_credcache_lock);
187         q = &auth->au_credcache[nr];
188         while ((cred = *q) != NULL) {
189                 if (!(cred->cr_flags & RPCAUTH_CRED_DEAD) &&
190                     auth->au_ops->crmatch(cred, taskflags)) {
191                         *q = cred->cr_next;
192                         break;
193                 }
194                 q = &cred->cr_next;
195         }
196         spin_unlock(&rpc_credcache_lock);
197 
198         if (!cred) {
199                 cred = auth->au_ops->crcreate(taskflags);
200 #ifdef RPC_DEBUG
201                 if (cred)
202                         cred->cr_magic = RPCAUTH_CRED_MAGIC;
203 #endif
204         }
205 
206         if (cred)
207                 rpcauth_insert_credcache(auth, cred);
208 
209         return (struct rpc_cred *) cred;
210 }
211 
212 /*
213  * Remove cred handle from cache
214  */
215 static void
216 rpcauth_remove_credcache(struct rpc_auth *auth, struct rpc_cred *cred)
217 {
218         struct rpc_cred **q, *cr;
219         int             nr;
220 
221         nr = (cred->cr_uid & RPC_CREDCACHE_MASK);
222         spin_lock(&rpc_credcache_lock);
223         q = &auth->au_credcache[nr];
224         while ((cr = *q) != NULL) {
225                 if (cred == cr) {
226                         *q = cred->cr_next;
227                         cred->cr_next = NULL;
228                         break;
229                 }
230                 q = &cred->cr_next;
231         }
232         spin_unlock(&rpc_credcache_lock);
233 }
234 
235 struct rpc_cred *
236 rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
237 {
238         dprintk("RPC:     looking up %s cred\n",
239                 auth->au_ops->au_name);
240         return rpcauth_lookup_credcache(auth, taskflags);
241 }
242 
243 struct rpc_cred *
244 rpcauth_bindcred(struct rpc_task *task)
245 {
246         struct rpc_auth *auth = task->tk_auth;
247 
248         dprintk("RPC: %4d looking up %s cred\n",
249                 task->tk_pid, task->tk_auth->au_ops->au_name);
250         task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, task->tk_flags);
251         if (task->tk_msg.rpc_cred == 0)
252                 task->tk_status = -ENOMEM;
253         return task->tk_msg.rpc_cred;
254 }
255 
256 int
257 rpcauth_matchcred(struct rpc_auth *auth, struct rpc_cred *cred, int taskflags)
258 {
259         dprintk("RPC:     matching %s cred %d\n",
260                 auth->au_ops->au_name, taskflags);
261         return auth->au_ops->crmatch(cred, taskflags);
262 }
263 
264 void
265 rpcauth_holdcred(struct rpc_task *task)
266 {
267         dprintk("RPC: %4d holding %s cred %p\n",
268                 task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
269         if (task->tk_msg.rpc_cred) {
270                 task->tk_msg.rpc_cred->cr_count++;
271                 task->tk_msg.rpc_cred->cr_expire = jiffies + task->tk_auth->au_expire;
272         }
273 }
274 
275 void
276 rpcauth_releasecred(struct rpc_auth *auth, struct rpc_cred *cred)
277 {
278         if (cred != NULL && cred->cr_count > 0) {
279                 cred->cr_count--;
280                 if (cred->cr_flags & RPCAUTH_CRED_DEAD) {
281                         rpcauth_remove_credcache(auth, cred);
282                         if (!cred->cr_count)
283                                 rpcauth_crdestroy(auth, cred);
284                 }
285         }
286 }
287 
288 void
289 rpcauth_unbindcred(struct rpc_task *task)
290 {
291         struct rpc_auth *auth = task->tk_auth;
292         struct rpc_cred *cred = task->tk_msg.rpc_cred;
293 
294         dprintk("RPC: %4d releasing %s cred %p\n",
295                 task->tk_pid, auth->au_ops->au_name, cred);
296 
297         rpcauth_releasecred(auth, cred);
298         task->tk_msg.rpc_cred = NULL;
299 }
300 
301 u32 *
302 rpcauth_marshcred(struct rpc_task *task, u32 *p)
303 {
304         struct rpc_auth *auth = task->tk_auth;
305 
306         dprintk("RPC: %4d marshaling %s cred %p\n",
307                 task->tk_pid, auth->au_ops->au_name, task->tk_msg.rpc_cred);
308         return auth->au_ops->crmarshal(task, p,
309                                 task->tk_flags & RPC_CALL_REALUID);
310 }
311 
312 u32 *
313 rpcauth_checkverf(struct rpc_task *task, u32 *p)
314 {
315         struct rpc_auth *auth = task->tk_auth;
316 
317         dprintk("RPC: %4d validating %s cred %p\n",
318                 task->tk_pid, auth->au_ops->au_name, task->tk_msg.rpc_cred);
319         return auth->au_ops->crvalidate(task, p);
320 }
321 
322 int
323 rpcauth_refreshcred(struct rpc_task *task)
324 {
325         struct rpc_auth *auth = task->tk_auth;
326 
327         dprintk("RPC: %4d refreshing %s cred %p\n",
328                 task->tk_pid, auth->au_ops->au_name, task->tk_msg.rpc_cred);
329         task->tk_status = auth->au_ops->crrefresh(task);
330         return task->tk_status;
331 }
332 
333 void
334 rpcauth_invalcred(struct rpc_task *task)
335 {
336         dprintk("RPC: %4d invalidating %s cred %p\n",
337                 task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
338         if (task->tk_msg.rpc_cred)
339                 task->tk_msg.rpc_cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
340 }
341 
342 int
343 rpcauth_uptodatecred(struct rpc_task *task)
344 {
345         return !(task->tk_msg.rpc_cred) ||
346                 (task->tk_msg.rpc_cred->cr_flags & RPCAUTH_CRED_UPTODATE);
347 }
348 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.