Merge master.kernel.org:/pub/scm/linux/kernel/git/steve/gfs2-2.6-nmw
[pandora-kernel.git] / net / sunrpc / auth_gss / auth_gss.c
1 /*
2  * linux/net/sunrpc/auth_gss/auth_gss.c
3  *
4  * RPCSEC_GSS client authentication.
5  * 
6  *  Copyright (c) 2000 The Regents of the University of Michigan.
7  *  All rights reserved.
8  *
9  *  Dug Song       <dugsong@monkey.org>
10  *  Andy Adamson   <andros@umich.edu>
11  *
12  *  Redistribution and use in source and binary forms, with or without
13  *  modification, are permitted provided that the following conditions
14  *  are met:
15  *
16  *  1. Redistributions of source code must retain the above copyright
17  *     notice, this list of conditions and the following disclaimer.
18  *  2. Redistributions in binary form must reproduce the above copyright
19  *     notice, this list of conditions and the following disclaimer in the
20  *     documentation and/or other materials provided with the distribution.
21  *  3. Neither the name of the University nor the names of its
22  *     contributors may be used to endorse or promote products derived
23  *     from this software without specific prior written permission.
24  *
25  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  * $Id$
38  */
39
40
41 #include <linux/module.h>
42 #include <linux/init.h>
43 #include <linux/types.h>
44 #include <linux/slab.h>
45 #include <linux/sched.h>
46 #include <linux/pagemap.h>
47 #include <linux/sunrpc/clnt.h>
48 #include <linux/sunrpc/auth.h>
49 #include <linux/sunrpc/auth_gss.h>
50 #include <linux/sunrpc/svcauth_gss.h>
51 #include <linux/sunrpc/gss_err.h>
52 #include <linux/workqueue.h>
53 #include <linux/sunrpc/rpc_pipe_fs.h>
54 #include <linux/sunrpc/gss_api.h>
55 #include <asm/uaccess.h>
56
57 static struct rpc_authops authgss_ops;
58
59 static struct rpc_credops gss_credops;
60
61 #ifdef RPC_DEBUG
62 # define RPCDBG_FACILITY        RPCDBG_AUTH
63 #endif
64
65 #define NFS_NGROUPS     16
66
67 #define GSS_CRED_EXPIRE         (60 * HZ)       /* XXX: reasonable? */
68 #define GSS_CRED_SLACK          1024            /* XXX: unused */
69 /* length of a krb5 verifier (48), plus data added before arguments when
70  * using integrity (two 4-byte integers): */
71 #define GSS_VERF_SLACK          56
72
73 /* XXX this define must match the gssd define
74 * as it is passed to gssd to signal the use of
75 * machine creds should be part of the shared rpc interface */
76
77 #define CA_RUN_AS_MACHINE  0x00000200 
78
79 /* dump the buffer in `emacs-hexl' style */
80 #define isprint(c)      ((c > 0x1f) && (c < 0x7f))
81
82 static DEFINE_RWLOCK(gss_ctx_lock);
83
84 struct gss_auth {
85         struct rpc_auth rpc_auth;
86         struct gss_api_mech *mech;
87         enum rpc_gss_svc service;
88         struct list_head upcalls;
89         struct rpc_clnt *client;
90         struct dentry *dentry;
91         spinlock_t lock;
92 };
93
94 static void gss_destroy_ctx(struct gss_cl_ctx *);
95 static struct rpc_pipe_ops gss_upcall_ops;
96
97 void
98 print_hexl(u32 *p, u_int length, u_int offset)
99 {
100         u_int i, j, jm;
101         u8 c, *cp;
102         
103         dprintk("RPC: print_hexl: length %d\n",length);
104         dprintk("\n");
105         cp = (u8 *) p;
106         
107         for (i = 0; i < length; i += 0x10) {
108                 dprintk("  %04x: ", (u_int)(i + offset));
109                 jm = length - i;
110                 jm = jm > 16 ? 16 : jm;
111                 
112                 for (j = 0; j < jm; j++) {
113                         if ((j % 2) == 1)
114                                 dprintk("%02x ", (u_int)cp[i+j]);
115                         else
116                                 dprintk("%02x", (u_int)cp[i+j]);
117                 }
118                 for (; j < 16; j++) {
119                         if ((j % 2) == 1)
120                                 dprintk("   ");
121                         else
122                                 dprintk("  ");
123                 }
124                 dprintk(" ");
125                 
126                 for (j = 0; j < jm; j++) {
127                         c = cp[i+j];
128                         c = isprint(c) ? c : '.';
129                         dprintk("%c", c);
130                 }
131                 dprintk("\n");
132         }
133 }
134
135 EXPORT_SYMBOL(print_hexl);
136
137 static inline struct gss_cl_ctx *
138 gss_get_ctx(struct gss_cl_ctx *ctx)
139 {
140         atomic_inc(&ctx->count);
141         return ctx;
142 }
143
144 static inline void
145 gss_put_ctx(struct gss_cl_ctx *ctx)
146 {
147         if (atomic_dec_and_test(&ctx->count))
148                 gss_destroy_ctx(ctx);
149 }
150
151 static void
152 gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
153 {
154         struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
155         struct gss_cl_ctx *old;
156         write_lock(&gss_ctx_lock);
157         old = gss_cred->gc_ctx;
158         gss_cred->gc_ctx = ctx;
159         cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
160         cred->cr_flags &= ~RPCAUTH_CRED_NEW;
161         write_unlock(&gss_ctx_lock);
162         if (old)
163                 gss_put_ctx(old);
164 }
165
166 static int
167 gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
168 {
169         struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
170         int res = 0;
171
172         read_lock(&gss_ctx_lock);
173         if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
174                 res = 1;
175         read_unlock(&gss_ctx_lock);
176         return res;
177 }
178
179 static const void *
180 simple_get_bytes(const void *p, const void *end, void *res, size_t len)
181 {
182         const void *q = (const void *)((const char *)p + len);
183         if (unlikely(q > end || q < p))
184                 return ERR_PTR(-EFAULT);
185         memcpy(res, p, len);
186         return q;
187 }
188
189 static inline const void *
190 simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
191 {
192         const void *q;
193         unsigned int len;
194
195         p = simple_get_bytes(p, end, &len, sizeof(len));
196         if (IS_ERR(p))
197                 return p;
198         q = (const void *)((const char *)p + len);
199         if (unlikely(q > end || q < p))
200                 return ERR_PTR(-EFAULT);
201         dest->data = kmemdup(p, len, GFP_KERNEL);
202         if (unlikely(dest->data == NULL))
203                 return ERR_PTR(-ENOMEM);
204         dest->len = len;
205         return q;
206 }
207
208 static struct gss_cl_ctx *
209 gss_cred_get_ctx(struct rpc_cred *cred)
210 {
211         struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
212         struct gss_cl_ctx *ctx = NULL;
213
214         read_lock(&gss_ctx_lock);
215         if (gss_cred->gc_ctx)
216                 ctx = gss_get_ctx(gss_cred->gc_ctx);
217         read_unlock(&gss_ctx_lock);
218         return ctx;
219 }
220
221 static struct gss_cl_ctx *
222 gss_alloc_context(void)
223 {
224         struct gss_cl_ctx *ctx;
225
226         ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
227         if (ctx != NULL) {
228                 ctx->gc_proc = RPC_GSS_PROC_DATA;
229                 ctx->gc_seq = 1;        /* NetApp 6.4R1 doesn't accept seq. no. 0 */
230                 spin_lock_init(&ctx->gc_seq_lock);
231                 atomic_set(&ctx->count,1);
232         }
233         return ctx;
234 }
235
236 #define GSSD_MIN_TIMEOUT (60 * 60)
237 static const void *
238 gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm)
239 {
240         const void *q;
241         unsigned int seclen;
242         unsigned int timeout;
243         u32 window_size;
244         int ret;
245
246         /* First unsigned int gives the lifetime (in seconds) of the cred */
247         p = simple_get_bytes(p, end, &timeout, sizeof(timeout));
248         if (IS_ERR(p))
249                 goto err;
250         if (timeout == 0)
251                 timeout = GSSD_MIN_TIMEOUT;
252         ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4;
253         /* Sequence number window. Determines the maximum number of simultaneous requests */
254         p = simple_get_bytes(p, end, &window_size, sizeof(window_size));
255         if (IS_ERR(p))
256                 goto err;
257         ctx->gc_win = window_size;
258         /* gssd signals an error by passing ctx->gc_win = 0: */
259         if (ctx->gc_win == 0) {
260                 /* in which case, p points to  an error code which we ignore */
261                 p = ERR_PTR(-EACCES);
262                 goto err;
263         }
264         /* copy the opaque wire context */
265         p = simple_get_netobj(p, end, &ctx->gc_wire_ctx);
266         if (IS_ERR(p))
267                 goto err;
268         /* import the opaque security context */
269         p  = simple_get_bytes(p, end, &seclen, sizeof(seclen));
270         if (IS_ERR(p))
271                 goto err;
272         q = (const void *)((const char *)p + seclen);
273         if (unlikely(q > end || q < p)) {
274                 p = ERR_PTR(-EFAULT);
275                 goto err;
276         }
277         ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx);
278         if (ret < 0) {
279                 p = ERR_PTR(ret);
280                 goto err;
281         }
282         return q;
283 err:
284         dprintk("RPC:      gss_fill_context returning %ld\n", -PTR_ERR(p));
285         return p;
286 }
287
288
289 struct gss_upcall_msg {
290         atomic_t count;
291         uid_t   uid;
292         struct rpc_pipe_msg msg;
293         struct list_head list;
294         struct gss_auth *auth;
295         struct rpc_wait_queue rpc_waitqueue;
296         wait_queue_head_t waitqueue;
297         struct gss_cl_ctx *ctx;
298 };
299
300 static void
301 gss_release_msg(struct gss_upcall_msg *gss_msg)
302 {
303         if (!atomic_dec_and_test(&gss_msg->count))
304                 return;
305         BUG_ON(!list_empty(&gss_msg->list));
306         if (gss_msg->ctx != NULL)
307                 gss_put_ctx(gss_msg->ctx);
308         kfree(gss_msg);
309 }
310
311 static struct gss_upcall_msg *
312 __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
313 {
314         struct gss_upcall_msg *pos;
315         list_for_each_entry(pos, &gss_auth->upcalls, list) {
316                 if (pos->uid != uid)
317                         continue;
318                 atomic_inc(&pos->count);
319                 dprintk("RPC:      gss_find_upcall found msg %p\n", pos);
320                 return pos;
321         }
322         dprintk("RPC:      gss_find_upcall found nothing\n");
323         return NULL;
324 }
325
326 /* Try to add a upcall to the pipefs queue.
327  * If an upcall owned by our uid already exists, then we return a reference
328  * to that upcall instead of adding the new upcall.
329  */
330 static inline struct gss_upcall_msg *
331 gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
332 {
333         struct gss_upcall_msg *old;
334
335         spin_lock(&gss_auth->lock);
336         old = __gss_find_upcall(gss_auth, gss_msg->uid);
337         if (old == NULL) {
338                 atomic_inc(&gss_msg->count);
339                 list_add(&gss_msg->list, &gss_auth->upcalls);
340         } else
341                 gss_msg = old;
342         spin_unlock(&gss_auth->lock);
343         return gss_msg;
344 }
345
346 static void
347 __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
348 {
349         if (list_empty(&gss_msg->list))
350                 return;
351         list_del_init(&gss_msg->list);
352         rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
353         wake_up_all(&gss_msg->waitqueue);
354         atomic_dec(&gss_msg->count);
355 }
356
357 static void
358 gss_unhash_msg(struct gss_upcall_msg *gss_msg)
359 {
360         struct gss_auth *gss_auth = gss_msg->auth;
361
362         spin_lock(&gss_auth->lock);
363         __gss_unhash_msg(gss_msg);
364         spin_unlock(&gss_auth->lock);
365 }
366
367 static void
368 gss_upcall_callback(struct rpc_task *task)
369 {
370         struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
371                         struct gss_cred, gc_base);
372         struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
373
374         BUG_ON(gss_msg == NULL);
375         if (gss_msg->ctx)
376                 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
377         else
378                 task->tk_status = gss_msg->msg.errno;
379         spin_lock(&gss_msg->auth->lock);
380         gss_cred->gc_upcall = NULL;
381         rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
382         spin_unlock(&gss_msg->auth->lock);
383         gss_release_msg(gss_msg);
384 }
385
386 static inline struct gss_upcall_msg *
387 gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
388 {
389         struct gss_upcall_msg *gss_msg;
390
391         gss_msg = kzalloc(sizeof(*gss_msg), GFP_KERNEL);
392         if (gss_msg != NULL) {
393                 INIT_LIST_HEAD(&gss_msg->list);
394                 rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
395                 init_waitqueue_head(&gss_msg->waitqueue);
396                 atomic_set(&gss_msg->count, 1);
397                 gss_msg->msg.data = &gss_msg->uid;
398                 gss_msg->msg.len = sizeof(gss_msg->uid);
399                 gss_msg->uid = uid;
400                 gss_msg->auth = gss_auth;
401         }
402         return gss_msg;
403 }
404
405 static struct gss_upcall_msg *
406 gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
407 {
408         struct gss_upcall_msg *gss_new, *gss_msg;
409
410         gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
411         if (gss_new == NULL)
412                 return ERR_PTR(-ENOMEM);
413         gss_msg = gss_add_msg(gss_auth, gss_new);
414         if (gss_msg == gss_new) {
415                 int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg);
416                 if (res) {
417                         gss_unhash_msg(gss_new);
418                         gss_msg = ERR_PTR(res);
419                 }
420         } else
421                 gss_release_msg(gss_new);
422         return gss_msg;
423 }
424
425 static inline int
426 gss_refresh_upcall(struct rpc_task *task)
427 {
428         struct rpc_cred *cred = task->tk_msg.rpc_cred;
429         struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
430                         struct gss_auth, rpc_auth);
431         struct gss_cred *gss_cred = container_of(cred,
432                         struct gss_cred, gc_base);
433         struct gss_upcall_msg *gss_msg;
434         int err = 0;
435
436         dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid);
437         gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
438         if (IS_ERR(gss_msg)) {
439                 err = PTR_ERR(gss_msg);
440                 goto out;
441         }
442         spin_lock(&gss_auth->lock);
443         if (gss_cred->gc_upcall != NULL)
444                 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
445         else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
446                 task->tk_timeout = 0;
447                 gss_cred->gc_upcall = gss_msg;
448                 /* gss_upcall_callback will release the reference to gss_upcall_msg */
449                 atomic_inc(&gss_msg->count);
450                 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
451         } else
452                 err = gss_msg->msg.errno;
453         spin_unlock(&gss_auth->lock);
454         gss_release_msg(gss_msg);
455 out:
456         dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid,
457                         cred->cr_uid, err);
458         return err;
459 }
460
461 static inline int
462 gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
463 {
464         struct rpc_cred *cred = &gss_cred->gc_base;
465         struct gss_upcall_msg *gss_msg;
466         DEFINE_WAIT(wait);
467         int err = 0;
468
469         dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);
470         gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
471         if (IS_ERR(gss_msg)) {
472                 err = PTR_ERR(gss_msg);
473                 goto out;
474         }
475         for (;;) {
476                 prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
477                 spin_lock(&gss_auth->lock);
478                 if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
479                         spin_unlock(&gss_auth->lock);
480                         break;
481                 }
482                 spin_unlock(&gss_auth->lock);
483                 if (signalled()) {
484                         err = -ERESTARTSYS;
485                         goto out_intr;
486                 }
487                 schedule();
488         }
489         if (gss_msg->ctx)
490                 gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
491         else
492                 err = gss_msg->msg.errno;
493 out_intr:
494         finish_wait(&gss_msg->waitqueue, &wait);
495         gss_release_msg(gss_msg);
496 out:
497         dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err);
498         return err;
499 }
500
501 static ssize_t
502 gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
503                 char __user *dst, size_t buflen)
504 {
505         char *data = (char *)msg->data + msg->copied;
506         ssize_t mlen = msg->len;
507         ssize_t left;
508
509         if (mlen > buflen)
510                 mlen = buflen;
511         left = copy_to_user(dst, data, mlen);
512         if (left < 0) {
513                 msg->errno = left;
514                 return left;
515         }
516         mlen -= left;
517         msg->copied += mlen;
518         msg->errno = 0;
519         return mlen;
520 }
521
522 #define MSG_BUF_MAXSIZE 1024
523
524 static ssize_t
525 gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
526 {
527         const void *p, *end;
528         void *buf;
529         struct rpc_clnt *clnt;
530         struct gss_auth *gss_auth;
531         struct rpc_cred *cred;
532         struct gss_upcall_msg *gss_msg;
533         struct gss_cl_ctx *ctx;
534         uid_t uid;
535         int err = -EFBIG;
536
537         if (mlen > MSG_BUF_MAXSIZE)
538                 goto out;
539         err = -ENOMEM;
540         buf = kmalloc(mlen, GFP_KERNEL);
541         if (!buf)
542                 goto out;
543
544         clnt = RPC_I(filp->f_dentry->d_inode)->private;
545         err = -EFAULT;
546         if (copy_from_user(buf, src, mlen))
547                 goto err;
548
549         end = (const void *)((char *)buf + mlen);
550         p = simple_get_bytes(buf, end, &uid, sizeof(uid));
551         if (IS_ERR(p)) {
552                 err = PTR_ERR(p);
553                 goto err;
554         }
555
556         err = -ENOMEM;
557         ctx = gss_alloc_context();
558         if (ctx == NULL)
559                 goto err;
560         err = 0;
561         gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
562         p = gss_fill_context(p, end, ctx, gss_auth->mech);
563         if (IS_ERR(p)) {
564                 err = PTR_ERR(p);
565                 if (err != -EACCES)
566                         goto err_put_ctx;
567         }
568         spin_lock(&gss_auth->lock);
569         gss_msg = __gss_find_upcall(gss_auth, uid);
570         if (gss_msg) {
571                 if (err == 0 && gss_msg->ctx == NULL)
572                         gss_msg->ctx = gss_get_ctx(ctx);
573                 gss_msg->msg.errno = err;
574                 __gss_unhash_msg(gss_msg);
575                 spin_unlock(&gss_auth->lock);
576                 gss_release_msg(gss_msg);
577         } else {
578                 struct auth_cred acred = { .uid = uid };
579                 spin_unlock(&gss_auth->lock);
580                 cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
581                 if (IS_ERR(cred)) {
582                         err = PTR_ERR(cred);
583                         goto err_put_ctx;
584                 }
585                 gss_cred_set_ctx(cred, gss_get_ctx(ctx));
586         }
587         gss_put_ctx(ctx);
588         kfree(buf);
589         dprintk("RPC:      gss_pipe_downcall returning length %Zu\n", mlen);
590         return mlen;
591 err_put_ctx:
592         gss_put_ctx(ctx);
593 err:
594         kfree(buf);
595 out:
596         dprintk("RPC:      gss_pipe_downcall returning %d\n", err);
597         return err;
598 }
599
600 static void
601 gss_pipe_release(struct inode *inode)
602 {
603         struct rpc_inode *rpci = RPC_I(inode);
604         struct rpc_clnt *clnt;
605         struct rpc_auth *auth;
606         struct gss_auth *gss_auth;
607
608         clnt = rpci->private;
609         auth = clnt->cl_auth;
610         gss_auth = container_of(auth, struct gss_auth, rpc_auth);
611         spin_lock(&gss_auth->lock);
612         while (!list_empty(&gss_auth->upcalls)) {
613                 struct gss_upcall_msg *gss_msg;
614
615                 gss_msg = list_entry(gss_auth->upcalls.next,
616                                 struct gss_upcall_msg, list);
617                 gss_msg->msg.errno = -EPIPE;
618                 atomic_inc(&gss_msg->count);
619                 __gss_unhash_msg(gss_msg);
620                 spin_unlock(&gss_auth->lock);
621                 gss_release_msg(gss_msg);
622                 spin_lock(&gss_auth->lock);
623         }
624         spin_unlock(&gss_auth->lock);
625 }
626
627 static void
628 gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
629 {
630         struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);
631         static unsigned long ratelimit;
632
633         if (msg->errno < 0) {
634                 dprintk("RPC:      gss_pipe_destroy_msg releasing msg %p\n",
635                                 gss_msg);
636                 atomic_inc(&gss_msg->count);
637                 gss_unhash_msg(gss_msg);
638                 if (msg->errno == -ETIMEDOUT) {
639                         unsigned long now = jiffies;
640                         if (time_after(now, ratelimit)) {
641                                 printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
642                                                     "Please check user daemon is running!\n");
643                                 ratelimit = now + 15*HZ;
644                         }
645                 }
646                 gss_release_msg(gss_msg);
647         }
648 }
649
650 /* 
651  * NOTE: we have the opportunity to use different 
652  * parameters based on the input flavor (which must be a pseudoflavor)
653  */
654 static struct rpc_auth *
655 gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
656 {
657         struct gss_auth *gss_auth;
658         struct rpc_auth * auth;
659         int err = -ENOMEM; /* XXX? */
660
661         dprintk("RPC:      creating GSS authenticator for client %p\n",clnt);
662
663         if (!try_module_get(THIS_MODULE))
664                 return ERR_PTR(err);
665         if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
666                 goto out_dec;
667         gss_auth->client = clnt;
668         err = -EINVAL;
669         gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
670         if (!gss_auth->mech) {
671                 printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
672                                 __FUNCTION__, flavor);
673                 goto err_free;
674         }
675         gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
676         if (gss_auth->service == 0)
677                 goto err_put_mech;
678         INIT_LIST_HEAD(&gss_auth->upcalls);
679         spin_lock_init(&gss_auth->lock);
680         auth = &gss_auth->rpc_auth;
681         auth->au_cslack = GSS_CRED_SLACK >> 2;
682         auth->au_rslack = GSS_VERF_SLACK >> 2;
683         auth->au_ops = &authgss_ops;
684         auth->au_flavor = flavor;
685         atomic_set(&auth->au_count, 1);
686
687         err = rpcauth_init_credcache(auth, GSS_CRED_EXPIRE);
688         if (err)
689                 goto err_put_mech;
690
691         gss_auth->dentry = rpc_mkpipe(clnt->cl_dentry, gss_auth->mech->gm_name,
692                         clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
693         if (IS_ERR(gss_auth->dentry)) {
694                 err = PTR_ERR(gss_auth->dentry);
695                 goto err_put_mech;
696         }
697
698         return auth;
699 err_put_mech:
700         gss_mech_put(gss_auth->mech);
701 err_free:
702         kfree(gss_auth);
703 out_dec:
704         module_put(THIS_MODULE);
705         return ERR_PTR(err);
706 }
707
708 static void
709 gss_destroy(struct rpc_auth *auth)
710 {
711         struct gss_auth *gss_auth;
712
713         dprintk("RPC:      destroying GSS authenticator %p flavor %d\n",
714                 auth, auth->au_flavor);
715
716         gss_auth = container_of(auth, struct gss_auth, rpc_auth);
717         rpc_unlink(gss_auth->dentry);
718         gss_auth->dentry = NULL;
719         gss_mech_put(gss_auth->mech);
720
721         rpcauth_free_credcache(auth);
722         kfree(gss_auth);
723         module_put(THIS_MODULE);
724 }
725
726 /* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
727  * to create a new cred or context, so they check that things have been
728  * allocated before freeing them. */
729 static void
730 gss_destroy_ctx(struct gss_cl_ctx *ctx)
731 {
732         dprintk("RPC:      gss_destroy_ctx\n");
733
734         if (ctx->gc_gss_ctx)
735                 gss_delete_sec_context(&ctx->gc_gss_ctx);
736
737         kfree(ctx->gc_wire_ctx.data);
738         kfree(ctx);
739 }
740
741 static void
742 gss_destroy_cred(struct rpc_cred *rc)
743 {
744         struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
745
746         dprintk("RPC:      gss_destroy_cred \n");
747
748         if (cred->gc_ctx)
749                 gss_put_ctx(cred->gc_ctx);
750         kfree(cred);
751 }
752
753 /*
754  * Lookup RPCSEC_GSS cred for the current process
755  */
756 static struct rpc_cred *
757 gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
758 {
759         return rpcauth_lookup_credcache(auth, acred, flags);
760 }
761
762 static struct rpc_cred *
763 gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
764 {
765         struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
766         struct gss_cred *cred = NULL;
767         int err = -ENOMEM;
768
769         dprintk("RPC:      gss_create_cred for uid %d, flavor %d\n",
770                 acred->uid, auth->au_flavor);
771
772         if (!(cred = kzalloc(sizeof(*cred), GFP_KERNEL)))
773                 goto out_err;
774
775         atomic_set(&cred->gc_count, 1);
776         cred->gc_uid = acred->uid;
777         /*
778          * Note: in order to force a call to call_refresh(), we deliberately
779          * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
780          */
781         cred->gc_flags = 0;
782         cred->gc_base.cr_ops = &gss_credops;
783         cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
784         cred->gc_service = gss_auth->service;
785         return &cred->gc_base;
786
787 out_err:
788         dprintk("RPC:      gss_create_cred failed with error %d\n", err);
789         return ERR_PTR(err);
790 }
791
792 static int
793 gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred)
794 {
795         struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
796         struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base);
797         int err;
798
799         do {
800                 err = gss_create_upcall(gss_auth, gss_cred);
801         } while (err == -EAGAIN);
802         return err;
803 }
804
805 static int
806 gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
807 {
808         struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
809
810         /*
811          * If the searchflags have set RPCAUTH_LOOKUP_NEW, then
812          * we don't really care if the credential has expired or not,
813          * since the caller should be prepared to reinitialise it.
814          */
815         if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
816                 goto out;
817         /* Don't match with creds that have expired. */
818         if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
819                 return 0;
820 out:
821         return (rc->cr_uid == acred->uid);
822 }
823
824 /*
825 * Marshal credentials.
826 * Maybe we should keep a cached credential for performance reasons.
827 */
828 static __be32 *
829 gss_marshal(struct rpc_task *task, __be32 *p)
830 {
831         struct rpc_cred *cred = task->tk_msg.rpc_cred;
832         struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
833                                                  gc_base);
834         struct gss_cl_ctx       *ctx = gss_cred_get_ctx(cred);
835         __be32          *cred_len;
836         struct rpc_rqst *req = task->tk_rqstp;
837         u32             maj_stat = 0;
838         struct xdr_netobj mic;
839         struct kvec     iov;
840         struct xdr_buf  verf_buf;
841
842         dprintk("RPC: %4u gss_marshal\n", task->tk_pid);
843
844         *p++ = htonl(RPC_AUTH_GSS);
845         cred_len = p++;
846
847         spin_lock(&ctx->gc_seq_lock);
848         req->rq_seqno = ctx->gc_seq++;
849         spin_unlock(&ctx->gc_seq_lock);
850
851         *p++ = htonl((u32) RPC_GSS_VERSION);
852         *p++ = htonl((u32) ctx->gc_proc);
853         *p++ = htonl((u32) req->rq_seqno);
854         *p++ = htonl((u32) gss_cred->gc_service);
855         p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
856         *cred_len = htonl((p - (cred_len + 1)) << 2);
857
858         /* We compute the checksum for the verifier over the xdr-encoded bytes
859          * starting with the xid and ending at the end of the credential: */
860         iov.iov_base = xprt_skip_transport_header(task->tk_xprt,
861                                         req->rq_snd_buf.head[0].iov_base);
862         iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;
863         xdr_buf_from_iov(&iov, &verf_buf);
864
865         /* set verifier flavor*/
866         *p++ = htonl(RPC_AUTH_GSS);
867
868         mic.data = (u8 *)(p + 1);
869         maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
870         if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
871                 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
872         } else if (maj_stat != 0) {
873                 printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
874                 goto out_put_ctx;
875         }
876         p = xdr_encode_opaque(p, NULL, mic.len);
877         gss_put_ctx(ctx);
878         return p;
879 out_put_ctx:
880         gss_put_ctx(ctx);
881         return NULL;
882 }
883
884 /*
885 * Refresh credentials. XXX - finish
886 */
887 static int
888 gss_refresh(struct rpc_task *task)
889 {
890
891         if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
892                 return gss_refresh_upcall(task);
893         return 0;
894 }
895
896 static __be32 *
897 gss_validate(struct rpc_task *task, __be32 *p)
898 {
899         struct rpc_cred *cred = task->tk_msg.rpc_cred;
900         struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
901         __be32          seq;
902         struct kvec     iov;
903         struct xdr_buf  verf_buf;
904         struct xdr_netobj mic;
905         u32             flav,len;
906         u32             maj_stat;
907
908         dprintk("RPC: %4u gss_validate\n", task->tk_pid);
909
910         flav = ntohl(*p++);
911         if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE)
912                 goto out_bad;
913         if (flav != RPC_AUTH_GSS)
914                 goto out_bad;
915         seq = htonl(task->tk_rqstp->rq_seqno);
916         iov.iov_base = &seq;
917         iov.iov_len = sizeof(seq);
918         xdr_buf_from_iov(&iov, &verf_buf);
919         mic.data = (u8 *)p;
920         mic.len = len;
921
922         maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
923         if (maj_stat == GSS_S_CONTEXT_EXPIRED)
924                 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
925         if (maj_stat)
926                 goto out_bad;
927         /* We leave it to unwrap to calculate au_rslack. For now we just
928          * calculate the length of the verifier: */
929         task->tk_auth->au_verfsize = XDR_QUADLEN(len) + 2;
930         gss_put_ctx(ctx);
931         dprintk("RPC: %4u GSS gss_validate: gss_verify_mic succeeded.\n",
932                         task->tk_pid);
933         return p + XDR_QUADLEN(len);
934 out_bad:
935         gss_put_ctx(ctx);
936         dprintk("RPC: %4u gss_validate failed.\n", task->tk_pid);
937         return NULL;
938 }
939
940 static inline int
941 gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
942                 kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj)
943 {
944         struct xdr_buf  *snd_buf = &rqstp->rq_snd_buf;
945         struct xdr_buf  integ_buf;
946         __be32          *integ_len = NULL;
947         struct xdr_netobj mic;
948         u32             offset;
949         __be32          *q;
950         struct kvec     *iov;
951         u32             maj_stat = 0;
952         int             status = -EIO;
953
954         integ_len = p++;
955         offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
956         *p++ = htonl(rqstp->rq_seqno);
957
958         status = encode(rqstp, p, obj);
959         if (status)
960                 return status;
961
962         if (xdr_buf_subsegment(snd_buf, &integ_buf,
963                                 offset, snd_buf->len - offset))
964                 return status;
965         *integ_len = htonl(integ_buf.len);
966
967         /* guess whether we're in the head or the tail: */
968         if (snd_buf->page_len || snd_buf->tail[0].iov_len) 
969                 iov = snd_buf->tail;
970         else
971                 iov = snd_buf->head;
972         p = iov->iov_base + iov->iov_len;
973         mic.data = (u8 *)(p + 1);
974
975         maj_stat = gss_get_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
976         status = -EIO; /* XXX? */
977         if (maj_stat == GSS_S_CONTEXT_EXPIRED)
978                 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
979         else if (maj_stat)
980                 return status;
981         q = xdr_encode_opaque(p, NULL, mic.len);
982
983         offset = (u8 *)q - (u8 *)p;
984         iov->iov_len += offset;
985         snd_buf->len += offset;
986         return 0;
987 }
988
989 static void
990 priv_release_snd_buf(struct rpc_rqst *rqstp)
991 {
992         int i;
993
994         for (i=0; i < rqstp->rq_enc_pages_num; i++)
995                 __free_page(rqstp->rq_enc_pages[i]);
996         kfree(rqstp->rq_enc_pages);
997 }
998
999 static int
1000 alloc_enc_pages(struct rpc_rqst *rqstp)
1001 {
1002         struct xdr_buf *snd_buf = &rqstp->rq_snd_buf;
1003         int first, last, i;
1004
1005         if (snd_buf->page_len == 0) {
1006                 rqstp->rq_enc_pages_num = 0;
1007                 return 0;
1008         }
1009
1010         first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
1011         last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_CACHE_SHIFT;
1012         rqstp->rq_enc_pages_num = last - first + 1 + 1;
1013         rqstp->rq_enc_pages
1014                 = kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *),
1015                                 GFP_NOFS);
1016         if (!rqstp->rq_enc_pages)
1017                 goto out;
1018         for (i=0; i < rqstp->rq_enc_pages_num; i++) {
1019                 rqstp->rq_enc_pages[i] = alloc_page(GFP_NOFS);
1020                 if (rqstp->rq_enc_pages[i] == NULL)
1021                         goto out_free;
1022         }
1023         rqstp->rq_release_snd_buf = priv_release_snd_buf;
1024         return 0;
1025 out_free:
1026         for (i--; i >= 0; i--) {
1027                 __free_page(rqstp->rq_enc_pages[i]);
1028         }
1029 out:
1030         return -EAGAIN;
1031 }
1032
1033 static inline int
1034 gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1035                 kxdrproc_t encode, struct rpc_rqst *rqstp, __be32 *p, void *obj)
1036 {
1037         struct xdr_buf  *snd_buf = &rqstp->rq_snd_buf;
1038         u32             offset;
1039         u32             maj_stat;
1040         int             status;
1041         __be32          *opaque_len;
1042         struct page     **inpages;
1043         int             first;
1044         int             pad;
1045         struct kvec     *iov;
1046         char            *tmp;
1047
1048         opaque_len = p++;
1049         offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
1050         *p++ = htonl(rqstp->rq_seqno);
1051
1052         status = encode(rqstp, p, obj);
1053         if (status)
1054                 return status;
1055
1056         status = alloc_enc_pages(rqstp);
1057         if (status)
1058                 return status;
1059         first = snd_buf->page_base >> PAGE_CACHE_SHIFT;
1060         inpages = snd_buf->pages + first;
1061         snd_buf->pages = rqstp->rq_enc_pages;
1062         snd_buf->page_base -= first << PAGE_CACHE_SHIFT;
1063         /* Give the tail its own page, in case we need extra space in the
1064          * head when wrapping: */
1065         if (snd_buf->page_len || snd_buf->tail[0].iov_len) {
1066                 tmp = page_address(rqstp->rq_enc_pages[rqstp->rq_enc_pages_num - 1]);
1067                 memcpy(tmp, snd_buf->tail[0].iov_base, snd_buf->tail[0].iov_len);
1068                 snd_buf->tail[0].iov_base = tmp;
1069         }
1070         maj_stat = gss_wrap(ctx->gc_gss_ctx, offset, snd_buf, inpages);
1071         /* RPC_SLACK_SPACE should prevent this ever happening: */
1072         BUG_ON(snd_buf->len > snd_buf->buflen);
1073         status = -EIO;
1074         /* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was
1075          * done anyway, so it's safe to put the request on the wire: */
1076         if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1077                 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
1078         else if (maj_stat)
1079                 return status;
1080
1081         *opaque_len = htonl(snd_buf->len - offset);
1082         /* guess whether we're in the head or the tail: */
1083         if (snd_buf->page_len || snd_buf->tail[0].iov_len)
1084                 iov = snd_buf->tail;
1085         else
1086                 iov = snd_buf->head;
1087         p = iov->iov_base + iov->iov_len;
1088         pad = 3 - ((snd_buf->len - offset - 1) & 3);
1089         memset(p, 0, pad);
1090         iov->iov_len += pad;
1091         snd_buf->len += pad;
1092
1093         return 0;
1094 }
1095
1096 static int
1097 gss_wrap_req(struct rpc_task *task,
1098              kxdrproc_t encode, void *rqstp, __be32 *p, void *obj)
1099 {
1100         struct rpc_cred *cred = task->tk_msg.rpc_cred;
1101         struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
1102                         gc_base);
1103         struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
1104         int             status = -EIO;
1105
1106         dprintk("RPC: %4u gss_wrap_req\n", task->tk_pid);
1107         if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
1108                 /* The spec seems a little ambiguous here, but I think that not
1109                  * wrapping context destruction requests makes the most sense.
1110                  */
1111                 status = encode(rqstp, p, obj);
1112                 goto out;
1113         }
1114         switch (gss_cred->gc_service) {
1115                 case RPC_GSS_SVC_NONE:
1116                         status = encode(rqstp, p, obj);
1117                         break;
1118                 case RPC_GSS_SVC_INTEGRITY:
1119                         status = gss_wrap_req_integ(cred, ctx, encode,
1120                                                                 rqstp, p, obj);
1121                         break;
1122                 case RPC_GSS_SVC_PRIVACY:
1123                         status = gss_wrap_req_priv(cred, ctx, encode,
1124                                         rqstp, p, obj);
1125                         break;
1126         }
1127 out:
1128         gss_put_ctx(ctx);
1129         dprintk("RPC: %4u gss_wrap_req returning %d\n", task->tk_pid, status);
1130         return status;
1131 }
1132
1133 static inline int
1134 gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1135                 struct rpc_rqst *rqstp, __be32 **p)
1136 {
1137         struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
1138         struct xdr_buf integ_buf;
1139         struct xdr_netobj mic;
1140         u32 data_offset, mic_offset;
1141         u32 integ_len;
1142         u32 maj_stat;
1143         int status = -EIO;
1144
1145         integ_len = ntohl(*(*p)++);
1146         if (integ_len & 3)
1147                 return status;
1148         data_offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base;
1149         mic_offset = integ_len + data_offset;
1150         if (mic_offset > rcv_buf->len)
1151                 return status;
1152         if (ntohl(*(*p)++) != rqstp->rq_seqno)
1153                 return status;
1154
1155         if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset,
1156                                 mic_offset - data_offset))
1157                 return status;
1158
1159         if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
1160                 return status;
1161
1162         maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, &mic);
1163         if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1164                 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
1165         if (maj_stat != GSS_S_COMPLETE)
1166                 return status;
1167         return 0;
1168 }
1169
1170 static inline int
1171 gss_unwrap_resp_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
1172                 struct rpc_rqst *rqstp, __be32 **p)
1173 {
1174         struct xdr_buf  *rcv_buf = &rqstp->rq_rcv_buf;
1175         u32 offset;
1176         u32 opaque_len;
1177         u32 maj_stat;
1178         int status = -EIO;
1179
1180         opaque_len = ntohl(*(*p)++);
1181         offset = (u8 *)(*p) - (u8 *)rcv_buf->head[0].iov_base;
1182         if (offset + opaque_len > rcv_buf->len)
1183                 return status;
1184         /* remove padding: */
1185         rcv_buf->len = offset + opaque_len;
1186
1187         maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
1188         if (maj_stat == GSS_S_CONTEXT_EXPIRED)
1189                 cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
1190         if (maj_stat != GSS_S_COMPLETE)
1191                 return status;
1192         if (ntohl(*(*p)++) != rqstp->rq_seqno)
1193                 return status;
1194
1195         return 0;
1196 }
1197
1198
1199 static int
1200 gss_unwrap_resp(struct rpc_task *task,
1201                 kxdrproc_t decode, void *rqstp, __be32 *p, void *obj)
1202 {
1203         struct rpc_cred *cred = task->tk_msg.rpc_cred;
1204         struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
1205                         gc_base);
1206         struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
1207         __be32          *savedp = p;
1208         struct kvec     *head = ((struct rpc_rqst *)rqstp)->rq_rcv_buf.head;
1209         int             savedlen = head->iov_len;
1210         int             status = -EIO;
1211
1212         if (ctx->gc_proc != RPC_GSS_PROC_DATA)
1213                 goto out_decode;
1214         switch (gss_cred->gc_service) {
1215                 case RPC_GSS_SVC_NONE:
1216                         break;
1217                 case RPC_GSS_SVC_INTEGRITY:
1218                         status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
1219                         if (status)
1220                                 goto out;
1221                         break;
1222                 case RPC_GSS_SVC_PRIVACY:
1223                         status = gss_unwrap_resp_priv(cred, ctx, rqstp, &p);
1224                         if (status)
1225                                 goto out;
1226                         break;
1227         }
1228         /* take into account extra slack for integrity and privacy cases: */
1229         task->tk_auth->au_rslack = task->tk_auth->au_verfsize + (p - savedp)
1230                                                 + (savedlen - head->iov_len);
1231 out_decode:
1232         status = decode(rqstp, p, obj);
1233 out:
1234         gss_put_ctx(ctx);
1235         dprintk("RPC: %4u gss_unwrap_resp returning %d\n", task->tk_pid,
1236                         status);
1237         return status;
1238 }
1239   
1240 static struct rpc_authops authgss_ops = {
1241         .owner          = THIS_MODULE,
1242         .au_flavor      = RPC_AUTH_GSS,
1243 #ifdef RPC_DEBUG
1244         .au_name        = "RPCSEC_GSS",
1245 #endif
1246         .create         = gss_create,
1247         .destroy        = gss_destroy,
1248         .lookup_cred    = gss_lookup_cred,
1249         .crcreate       = gss_create_cred
1250 };
1251
1252 static struct rpc_credops gss_credops = {
1253         .cr_name        = "AUTH_GSS",
1254         .crdestroy      = gss_destroy_cred,
1255         .cr_init        = gss_cred_init,
1256         .crmatch        = gss_match,
1257         .crmarshal      = gss_marshal,
1258         .crrefresh      = gss_refresh,
1259         .crvalidate     = gss_validate,
1260         .crwrap_req     = gss_wrap_req,
1261         .crunwrap_resp  = gss_unwrap_resp,
1262 };
1263
1264 static struct rpc_pipe_ops gss_upcall_ops = {
1265         .upcall         = gss_pipe_upcall,
1266         .downcall       = gss_pipe_downcall,
1267         .destroy_msg    = gss_pipe_destroy_msg,
1268         .release_pipe   = gss_pipe_release,
1269 };
1270
1271 /*
1272  * Initialize RPCSEC_GSS module
1273  */
1274 static int __init init_rpcsec_gss(void)
1275 {
1276         int err = 0;
1277
1278         err = rpcauth_register(&authgss_ops);
1279         if (err)
1280                 goto out;
1281         err = gss_svc_init();
1282         if (err)
1283                 goto out_unregister;
1284         return 0;
1285 out_unregister:
1286         rpcauth_unregister(&authgss_ops);
1287 out:
1288         return err;
1289 }
1290
1291 static void __exit exit_rpcsec_gss(void)
1292 {
1293         gss_svc_shutdown();
1294         rpcauth_unregister(&authgss_ops);
1295 }
1296
1297 MODULE_LICENSE("GPL");
1298 module_init(init_rpcsec_gss)
1299 module_exit(exit_rpcsec_gss)