Showing error 1774

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: net/sunrpc/auth_gss/auth_gss.c
Line in file: 362
Project: Linux Kernel
Project version: 2.6.28
Tools: Smatch (1.59)
Entered: 2013-09-10 20:24:52 UTC


Source:

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