2 * linux/net/sunrpc/auth_gss.c
4 * RPCSEC_GSS client authentication.
6 * Copyright (c) 2000 The Regents of the University of Michigan.
9 * Dug Song <dugsong@monkey.org>
10 * Andy Adamson <andros@umich.edu>
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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.
41 #include <linux/module.h>
42 #include <linux/init.h>
43 #include <linux/types.h>
44 #include <linux/slab.h>
45 #include <linux/socket.h>
47 #include <linux/sched.h>
48 #include <linux/sunrpc/clnt.h>
49 #include <linux/sunrpc/auth.h>
50 #include <linux/sunrpc/auth_gss.h>
51 #include <linux/sunrpc/svcauth_gss.h>
52 #include <linux/sunrpc/gss_err.h>
53 #include <linux/workqueue.h>
54 #include <linux/sunrpc/rpc_pipe_fs.h>
55 #include <linux/sunrpc/gss_api.h>
56 #include <asm/uaccess.h>
58 static struct rpc_authops authgss_ops;
60 static struct rpc_credops gss_credops;
63 # define RPCDBG_FACILITY RPCDBG_AUTH
66 #define NFS_NGROUPS 16
68 #define GSS_CRED_EXPIRE (60 * HZ) /* XXX: reasonable? */
69 #define GSS_CRED_SLACK 1024 /* XXX: unused */
70 /* length of a krb5 verifier (48), plus data added before arguments when
71 * using integrity (two 4-byte integers): */
72 #define GSS_VERF_SLACK 56
74 /* XXX this define must match the gssd define
75 * as it is passed to gssd to signal the use of
76 * machine creds should be part of the shared rpc interface */
78 #define CA_RUN_AS_MACHINE 0x00000200
80 /* dump the buffer in `emacs-hexl' style */
81 #define isprint(c) ((c > 0x1f) && (c < 0x7f))
83 static rwlock_t gss_ctx_lock = RW_LOCK_UNLOCKED;
86 struct rpc_auth rpc_auth;
87 struct gss_api_mech *mech;
88 struct list_head upcalls;
89 struct dentry *dentry;
94 static void gss_destroy_ctx(struct gss_cl_ctx *);
95 static struct rpc_pipe_ops gss_upcall_ops;
98 print_hexl(u32 *p, u_int length, u_int offset)
103 dprintk("RPC: print_hexl: length %d\n",length);
107 for (i = 0; i < length; i += 0x10) {
108 dprintk(" %04x: ", (u_int)(i + offset));
110 jm = jm > 16 ? 16 : jm;
112 for (j = 0; j < jm; j++) {
114 dprintk("%02x ", (u_int)cp[i+j]);
116 dprintk("%02x", (u_int)cp[i+j]);
118 for (; j < 16; j++) {
126 for (j = 0; j < jm; j++) {
128 c = isprint(c) ? c : '.';
135 static inline struct gss_cl_ctx *
136 gss_get_ctx(struct gss_cl_ctx *ctx)
138 atomic_inc(&ctx->count);
143 gss_put_ctx(struct gss_cl_ctx *ctx)
145 if (atomic_dec_and_test(&ctx->count))
146 gss_destroy_ctx(ctx);
150 gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
152 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
153 struct gss_cl_ctx *old;
154 write_lock(&gss_ctx_lock);
155 old = gss_cred->gc_ctx;
156 gss_cred->gc_ctx = ctx;
157 cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
158 write_unlock(&gss_ctx_lock);
164 gss_cred_is_uptodate_ctx(struct rpc_cred *cred)
166 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
169 read_lock(&gss_ctx_lock);
170 if ((cred->cr_flags & RPCAUTH_CRED_UPTODATE) && gss_cred->gc_ctx)
172 read_unlock(&gss_ctx_lock);
177 simple_get_bytes(char **ptr, const char *end, void *res, int len)
182 if (q > end || q < p)
190 simple_get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
194 if (simple_get_bytes(&p, end, &res->len, sizeof(res->len)))
197 if (q > end || q < p)
205 dup_netobj(struct xdr_netobj *source, struct xdr_netobj *dest)
207 dest->len = source->len;
208 if (!(dest->data = kmalloc(dest->len, GFP_KERNEL)))
210 memcpy(dest->data, source->data, dest->len);
214 static struct gss_cl_ctx *
215 gss_cred_get_ctx(struct rpc_cred *cred)
217 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
218 struct gss_cl_ctx *ctx = NULL;
220 read_lock(&gss_ctx_lock);
221 if (gss_cred->gc_ctx)
222 ctx = gss_get_ctx(gss_cred->gc_ctx);
223 read_unlock(&gss_ctx_lock);
228 gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
229 struct gss_cl_ctx **gc, uid_t *uid, int *gss_err)
231 char *end = buf->data + buf->len;
233 struct gss_cl_ctx *ctx;
234 struct xdr_netobj tmp_buf;
235 unsigned int timeout;
238 if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL))) {
242 ctx->gc_proc = RPC_GSS_PROC_DATA;
243 ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
244 spin_lock_init(&ctx->gc_seq_lock);
245 atomic_set(&ctx->count,1);
247 if (simple_get_bytes(&p, end, uid, sizeof(uid)))
249 /* FIXME: discarded timeout for now */
250 if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
253 if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win)))
255 /* gssd signals an error by passing ctx->gc_win = 0: */
257 /* in which case the next int is an error code: */
258 if (simple_get_bytes(&p, end, gss_err, sizeof(*gss_err)))
263 if (simple_get_netobj(&p, end, &tmp_buf))
265 if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) {
269 if (simple_get_netobj(&p, end, &tmp_buf))
270 goto err_free_wire_ctx;
272 goto err_free_wire_ctx;
273 if (gss_import_sec_context(&tmp_buf, gm, &ctx->gc_gss_ctx))
274 goto err_free_wire_ctx;
278 kfree(ctx->gc_wire_ctx.data);
283 dprintk("RPC: gss_parse_init_downcall returning %d\n", err);
288 struct gss_upcall_msg {
289 struct rpc_pipe_msg msg;
290 struct list_head list;
291 struct gss_auth *auth;
292 struct rpc_wait_queue waitq;
298 gss_release_msg(struct gss_upcall_msg *gss_msg)
300 if (!atomic_dec_and_test(&gss_msg->count))
302 BUG_ON(!list_empty(&gss_msg->list));
306 static struct gss_upcall_msg *
307 __gss_find_upcall(struct gss_auth *gss_auth, uid_t uid)
309 struct gss_upcall_msg *pos;
310 list_for_each_entry(pos, &gss_auth->upcalls, list) {
313 atomic_inc(&pos->count);
320 __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
322 if (list_empty(&gss_msg->list))
324 list_del_init(&gss_msg->list);
325 if (gss_msg->msg.errno < 0)
326 rpc_wake_up_status(&gss_msg->waitq, gss_msg->msg.errno);
328 rpc_wake_up(&gss_msg->waitq);
329 atomic_dec(&gss_msg->count);
333 gss_unhash_msg(struct gss_upcall_msg *gss_msg)
335 struct gss_auth *gss_auth = gss_msg->auth;
337 spin_lock(&gss_auth->lock);
338 __gss_unhash_msg(gss_msg);
339 spin_unlock(&gss_auth->lock);
343 gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, struct rpc_cred *cred)
345 struct gss_auth *gss_auth = container_of(clnt->cl_auth,
346 struct gss_auth, rpc_auth);
347 struct gss_upcall_msg *gss_msg, *gss_new = NULL;
348 struct rpc_pipe_msg *msg;
349 struct dentry *dentry = gss_auth->dentry;
350 uid_t uid = cred->cr_uid;
354 spin_lock(&gss_auth->lock);
355 gss_msg = __gss_find_upcall(gss_auth, uid);
358 if (gss_new == NULL) {
359 spin_unlock(&gss_auth->lock);
360 gss_new = kmalloc(sizeof(*gss_new), GFP_KERNEL);
366 memset(gss_new, 0, sizeof(*gss_new));
367 INIT_LIST_HEAD(&gss_new->list);
368 rpc_init_wait_queue(&gss_new->waitq, "RPCSEC_GSS upcall waitq");
369 atomic_set(&gss_new->count, 2);
371 msg->data = &gss_new->uid;
372 msg->len = sizeof(gss_new->uid);
374 gss_new->auth = gss_auth;
375 list_add(&gss_new->list, &gss_auth->upcalls);
377 /* Has someone updated the credential behind our back? */
378 if (!gss_cred_is_uptodate_ctx(cred)) {
379 /* No, so do upcall and sleep */
380 task->tk_timeout = 0;
381 rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
382 spin_unlock(&gss_auth->lock);
383 res = rpc_queue_upcall(dentry->d_inode, msg);
385 gss_unhash_msg(gss_msg);
387 /* Yes, so cancel upcall */
388 __gss_unhash_msg(gss_msg);
389 spin_unlock(&gss_auth->lock);
391 gss_release_msg(gss_msg);
395 task->tk_timeout = 0;
396 rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
397 spin_unlock(&gss_auth->lock);
400 /* Note: we drop the reference here: we are automatically removed
401 * from the queue when we're woken up, and we should in any case
402 * have no further responsabilities w.r.t. the upcall.
404 gss_release_msg(gss_msg);
409 gss_pipe_upcall(struct file *filp, struct rpc_pipe_msg *msg,
410 char *dst, size_t buflen)
412 char *data = (char *)msg->data + msg->copied;
413 ssize_t mlen = msg->len;
418 left = copy_to_user(dst, data, mlen);
430 gss_pipe_downcall(struct file *filp, const char *src, size_t mlen)
433 struct xdr_netobj obj = {
437 struct inode *inode = filp->f_dentry->d_inode;
438 struct rpc_inode *rpci = RPC_I(inode);
439 struct rpc_clnt *clnt;
440 struct rpc_auth *auth;
441 struct gss_auth *gss_auth;
442 struct gss_api_mech *mech;
443 struct auth_cred acred = { 0 };
444 struct rpc_cred *cred;
445 struct gss_upcall_msg *gss_msg;
446 struct gss_cl_ctx *ctx = NULL;
451 if (mlen > sizeof(buf))
453 left = copy_from_user(buf, src, mlen);
456 clnt = rpci->private;
457 atomic_inc(&clnt->cl_users);
458 auth = clnt->cl_auth;
459 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
460 mech = gss_auth->mech;
461 err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid, &gss_err);
464 cred = rpcauth_lookup_credcache(auth, &acred, 0);
468 cred->cr_flags |= RPCAUTH_CRED_DEAD;
470 gss_cred_set_ctx(cred, ctx);
471 spin_lock(&gss_auth->lock);
472 gss_msg = __gss_find_upcall(gss_auth, acred.uid);
474 __gss_unhash_msg(gss_msg);
475 spin_unlock(&gss_auth->lock);
476 gss_release_msg(gss_msg);
478 spin_unlock(&gss_auth->lock);
479 rpc_release_client(clnt);
483 gss_destroy_ctx(ctx);
484 rpc_release_client(clnt);
485 dprintk("RPC: gss_pipe_downcall returning %d\n", err);
490 gss_pipe_release(struct inode *inode)
492 struct rpc_inode *rpci = RPC_I(inode);
493 struct rpc_clnt *clnt;
494 struct rpc_auth *auth;
495 struct gss_auth *gss_auth;
497 clnt = rpci->private;
498 auth = clnt->cl_auth;
499 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
500 spin_lock(&gss_auth->lock);
501 while (!list_empty(&gss_auth->upcalls)) {
502 struct gss_upcall_msg *gss_msg;
504 gss_msg = list_entry(gss_auth->upcalls.next,
505 struct gss_upcall_msg, list);
506 gss_msg->msg.errno = -EPIPE;
507 atomic_inc(&gss_msg->count);
508 __gss_unhash_msg(gss_msg);
509 spin_unlock(&gss_auth->lock);
510 gss_release_msg(gss_msg);
511 spin_lock(&gss_auth->lock);
513 spin_unlock(&gss_auth->lock);
517 gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
519 struct gss_upcall_msg *gss_msg = container_of(msg, struct gss_upcall_msg, msg);
520 static unsigned long ratelimit;
522 if (msg->errno < 0) {
523 atomic_inc(&gss_msg->count);
524 gss_unhash_msg(gss_msg);
525 if (msg->errno == -ETIMEDOUT || msg->errno == -EPIPE) {
526 unsigned long now = jiffies;
527 if (time_after(now, ratelimit)) {
528 printk(KERN_WARNING "RPC: AUTH_GSS upcall timed out.\n"
529 "Please check user daemon is running!\n");
530 ratelimit = now + 15*HZ;
533 gss_release_msg(gss_msg);
538 * NOTE: we have the opportunity to use different
539 * parameters based on the input flavor (which must be a pseudoflavor)
541 static struct rpc_auth *
542 gss_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
544 struct gss_auth *gss_auth;
545 struct rpc_auth * auth;
547 dprintk("RPC: creating GSS authenticator for client %p\n",clnt);
548 if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
550 gss_auth->mech = gss_pseudoflavor_to_mech(flavor);
551 if (!gss_auth->mech) {
552 printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
553 __FUNCTION__, flavor);
556 INIT_LIST_HEAD(&gss_auth->upcalls);
557 spin_lock_init(&gss_auth->lock);
558 auth = &gss_auth->rpc_auth;
559 auth->au_cslack = GSS_CRED_SLACK >> 2;
560 auth->au_rslack = GSS_VERF_SLACK >> 2;
561 auth->au_expire = GSS_CRED_EXPIRE;
562 auth->au_ops = &authgss_ops;
563 auth->au_flavor = flavor;
565 rpcauth_init_credcache(auth);
567 snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
569 gss_auth->mech->gm_ops->name);
570 gss_auth->dentry = rpc_mkpipe(gss_auth->path, clnt, &gss_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
571 if (IS_ERR(gss_auth->dentry))
582 gss_destroy(struct rpc_auth *auth)
584 struct gss_auth *gss_auth;
585 dprintk("RPC: destroying GSS authenticator %p flavor %d\n",
586 auth, auth->au_flavor);
588 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
589 rpc_unlink(gss_auth->path);
591 rpcauth_free_credcache(auth);
594 /* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
595 * to create a new cred or context, so they check that things have been
596 * allocated before freeing them. */
598 gss_destroy_ctx(struct gss_cl_ctx *ctx)
601 dprintk("RPC: gss_destroy_ctx\n");
604 gss_delete_sec_context(&ctx->gc_gss_ctx);
606 if (ctx->gc_wire_ctx.len > 0) {
607 kfree(ctx->gc_wire_ctx.data);
608 ctx->gc_wire_ctx.len = 0;
616 gss_destroy_cred(struct rpc_cred *rc)
618 struct gss_cred *cred = (struct gss_cred *)rc;
620 dprintk("RPC: gss_destroy_cred \n");
623 gss_put_ctx(cred->gc_ctx);
627 static struct rpc_cred *
628 gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
630 struct gss_cred *cred = NULL;
632 dprintk("RPC: gss_create_cred for uid %d, flavor %d\n",
633 acred->uid, auth->au_flavor);
635 if (!(cred = kmalloc(sizeof(*cred), GFP_KERNEL)))
638 memset(cred, 0, sizeof(*cred));
639 atomic_set(&cred->gc_count, 0);
640 cred->gc_uid = acred->uid;
642 * Note: in order to force a call to call_refresh(), we deliberately
643 * fail to flag the credential as RPCAUTH_CRED_UPTODATE.
646 cred->gc_base.cr_ops = &gss_credops;
647 cred->gc_flavor = auth->au_flavor;
649 return (struct rpc_cred *) cred;
652 dprintk("RPC: gss_create_cred failed\n");
653 if (cred) gss_destroy_cred((struct rpc_cred *)cred);
658 gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
660 return (rc->cr_uid == acred->uid);
664 * Marshal credentials.
665 * Maybe we should keep a cached credential for performance reasons.
668 gss_marshal(struct rpc_task *task, u32 *p, int ruid)
670 struct rpc_cred *cred = task->tk_msg.rpc_cred;
671 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
673 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
675 struct rpc_rqst *req = task->tk_rqstp;
677 struct xdr_netobj mic;
679 struct xdr_buf verf_buf;
682 dprintk("RPC: gss_marshal\n");
684 *p++ = htonl(RPC_AUTH_GSS);
687 service = gss_pseudoflavor_to_service(gss_cred->gc_flavor);
689 dprintk("Bad pseudoflavor %d in gss_marshal\n",
690 gss_cred->gc_flavor);
693 spin_lock(&ctx->gc_seq_lock);
694 req->rq_seqno = ctx->gc_seq++;
695 spin_unlock(&ctx->gc_seq_lock);
697 *p++ = htonl((u32) RPC_GSS_VERSION);
698 *p++ = htonl((u32) ctx->gc_proc);
699 *p++ = htonl((u32) req->rq_seqno);
700 *p++ = htonl((u32) service);
701 p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
702 *cred_len = htonl((p - (cred_len + 1)) << 2);
704 /* We compute the checksum for the verifier over the xdr-encoded bytes
705 * starting with the xid and ending at the end of the credential: */
706 iov.iov_base = req->rq_snd_buf.head[0].iov_base;
707 if (task->tk_client->cl_xprt->stream)
708 /* See clnt.c:call_header() */
710 iov.iov_len = (u8 *)p - (u8 *)iov.iov_base;
711 xdr_buf_from_iov(&iov, &verf_buf);
713 /* set verifier flavor*/
714 *p++ = htonl(RPC_AUTH_GSS);
716 mic.data = (u8 *)(p + 1);
717 maj_stat = gss_get_mic(ctx->gc_gss_ctx,
721 printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
724 p = xdr_encode_opaque(p, NULL, mic.len);
733 * Refresh credentials. XXX - finish
736 gss_refresh(struct rpc_task *task)
738 struct rpc_clnt *clnt = task->tk_client;
739 struct rpc_xprt *xprt = task->tk_xprt;
740 struct rpc_cred *cred = task->tk_msg.rpc_cred;
742 task->tk_timeout = xprt->timeout.to_current;
743 if (!gss_cred_is_uptodate_ctx(cred))
744 return gss_upcall(clnt, task, cred);
749 gss_validate(struct rpc_task *task, u32 *p)
751 struct rpc_cred *cred = task->tk_msg.rpc_cred;
752 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
754 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
757 struct xdr_buf verf_buf;
758 struct xdr_netobj mic;
762 dprintk("RPC: gss_validate\n");
765 if ((len = ntohl(*p++)) > RPC_MAX_AUTH_SIZE)
767 if (flav != RPC_AUTH_GSS)
769 seq = htonl(task->tk_rqstp->rq_seqno);
771 iov.iov_len = sizeof(seq);
772 xdr_buf_from_iov(&iov, &verf_buf);
776 if (gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state))
778 service = gss_pseudoflavor_to_service(gss_cred->gc_flavor);
780 case RPC_GSS_SVC_NONE:
781 /* verifier data, flavor, length: */
782 task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
784 case RPC_GSS_SVC_INTEGRITY:
785 /* verifier data, flavor, length, length, sequence number: */
786 task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
792 return p + XDR_QUADLEN(len);
799 gss_wrap_req(struct rpc_task *task,
800 kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
802 struct rpc_rqst *req = (struct rpc_rqst *)rqstp;
803 struct xdr_buf *snd_buf = &req->rq_snd_buf;
804 struct rpc_cred *cred = task->tk_msg.rpc_cred;
805 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
807 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
808 u32 *integ_len = NULL;
811 struct xdr_buf integ_buf;
812 struct xdr_netobj mic;
817 dprintk("RPC: gss_wrap_body\n");
819 if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
820 /* The spec seems a little ambiguous here, but I think that not
821 * wrapping context destruction requests makes the most sense.
823 status = encode(rqstp, p, obj);
826 service = gss_pseudoflavor_to_service(gss_cred->gc_flavor);
828 case RPC_GSS_SVC_NONE:
829 status = encode(rqstp, p, obj);
831 case RPC_GSS_SVC_INTEGRITY:
834 offset = (u8 *)p - (u8 *)snd_buf->head[0].iov_base;
835 *p++ = htonl(req->rq_seqno);
837 status = encode(rqstp, p, obj);
841 if (xdr_buf_subsegment(snd_buf, &integ_buf,
842 offset, snd_buf->len - offset))
844 *integ_len = htonl(integ_buf.len);
846 /* guess whether we're in the head or the tail: */
847 if (snd_buf->page_len || snd_buf->tail[0].iov_len)
851 p = iov->iov_base + iov->iov_len;
852 mic.data = (u8 *)(p + 1);
854 maj_stat = gss_get_mic(ctx->gc_gss_ctx,
855 GSS_C_QOP_DEFAULT, &integ_buf, &mic);
856 status = -EIO; /* XXX? */
859 q = xdr_encode_opaque(p, NULL, mic.len);
861 offset = (u8 *)q - (u8 *)p;
862 iov->iov_len += offset;
863 snd_buf->len += offset;
865 case RPC_GSS_SVC_PRIVACY:
872 dprintk("RPC: gss_wrap_req returning %d\n", status);
877 gss_unwrap_resp(struct rpc_task *task,
878 kxdrproc_t decode, void *rqstp, u32 *p, void *obj)
880 struct rpc_rqst *req = (struct rpc_rqst *)rqstp;
881 struct xdr_buf *rcv_buf = &req->rq_rcv_buf;
882 struct rpc_cred *cred = task->tk_msg.rpc_cred;
883 struct gss_cred *gss_cred = container_of(cred, struct gss_cred,
885 struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
886 struct xdr_buf integ_buf;
887 struct xdr_netobj mic;
891 u32 data_offset, mic_offset;
896 if (ctx->gc_proc != RPC_GSS_PROC_DATA)
898 service = gss_pseudoflavor_to_service(gss_cred->gc_flavor);
900 case RPC_GSS_SVC_NONE:
902 case RPC_GSS_SVC_INTEGRITY:
903 integ_len = ntohl(*p++);
906 data_offset = (u8 *)p - (u8 *)rcv_buf->head[0].iov_base;
907 mic_offset = integ_len + data_offset;
908 if (mic_offset > rcv_buf->len)
910 if (ntohl(*p++) != req->rq_seqno)
913 if (xdr_buf_subsegment(rcv_buf, &integ_buf, data_offset,
914 mic_offset - data_offset))
917 if (xdr_buf_read_netobj(rcv_buf, &mic, mic_offset))
920 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
922 if (maj_stat != GSS_S_COMPLETE)
925 case RPC_GSS_SVC_PRIVACY:
930 status = decode(rqstp, p, obj);
933 dprintk("RPC: gss_unwrap_resp returning %d\n", status);
937 static struct rpc_authops authgss_ops = {
938 .owner = THIS_MODULE,
939 .au_flavor = RPC_AUTH_GSS,
941 .au_name = "RPCSEC_GSS",
943 .create = gss_create,
944 .destroy = gss_destroy,
945 .crcreate = gss_create_cred
948 static struct rpc_credops gss_credops = {
949 .crdestroy = gss_destroy_cred,
950 .crmatch = gss_match,
951 .crmarshal = gss_marshal,
952 .crrefresh = gss_refresh,
953 .crvalidate = gss_validate,
954 .crwrap_req = gss_wrap_req,
955 .crunwrap_resp = gss_unwrap_resp,
958 static struct rpc_pipe_ops gss_upcall_ops = {
959 .upcall = gss_pipe_upcall,
960 .downcall = gss_pipe_downcall,
961 .destroy_msg = gss_pipe_destroy_msg,
962 .release_pipe = gss_pipe_release,
966 * Initialize RPCSEC_GSS module
968 static int __init init_rpcsec_gss(void)
972 err = rpcauth_register(&authgss_ops);
975 err = gss_svc_init();
980 rpcauth_unregister(&authgss_ops);
985 static void __exit exit_rpcsec_gss(void)
988 gss_mech_unregister_all();
989 rpcauth_unregister(&authgss_ops);
992 MODULE_LICENSE("GPL");
993 module_init(init_rpcsec_gss)
994 module_exit(exit_rpcsec_gss)