]> err.no Git - linux-2.6/blobdiff - net/sunrpc/auth_gss/svcauth_gss.c
Merge branch 'audit.b32' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit...
[linux-2.6] / net / sunrpc / auth_gss / svcauth_gss.c
index cd3d77ca3a31064651ad139d8c5fbc0b6388f422..447d9aef46051ebc9fd810bc96b01e92113c61f1 100644 (file)
@@ -620,7 +620,7 @@ svc_safe_getnetobj(struct kvec *argv, struct xdr_netobj *o)
 static inline int
 svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
 {
-       u32 *p;
+       u8 *p;
 
        if (resv->iov_len + 4 > PAGE_SIZE)
                return -1;
@@ -630,7 +630,7 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
        if (resv->iov_len > PAGE_SIZE)
                return -1;
        memcpy(p, o->data, o->len);
-       memset((u8 *)p + o->len, 0, round_up_to_quad(o->len) - o->len);
+       memset(p + o->len, 0, round_up_to_quad(o->len) - o->len);
        return 0;
 }
 
@@ -640,7 +640,7 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
  */
 static int
 gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
-                 u32 *rpcstart, struct rpc_gss_wire_cred *gc, u32 *authp)
+                 __be32 *rpcstart, struct rpc_gss_wire_cred *gc, __be32 *authp)
 {
        struct gss_ctx          *ctx_id = rsci->mechctx;
        struct xdr_buf          rpchdr;
@@ -687,7 +687,7 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
 static int
 gss_write_null_verf(struct svc_rqst *rqstp)
 {
-       u32     *p;
+       __be32     *p;
 
        svc_putnl(rqstp->rq_res.head, RPC_AUTH_NULL);
        p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
@@ -701,11 +701,11 @@ gss_write_null_verf(struct svc_rqst *rqstp)
 static int
 gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 {
-       u32                     xdr_seq;
+       __be32                  xdr_seq;
        u32                     maj_stat;
        struct xdr_buf          verf_data;
        struct xdr_netobj       mic;
-       u32                     *p;
+       __be32                  *p;
        struct kvec             iov;
 
        svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
@@ -782,7 +782,7 @@ EXPORT_SYMBOL(svcauth_gss_register_pseudoflavor);
 static inline int
 read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
 {
-       u32     raw;
+       __be32  raw;
        int     status;
 
        status = read_bytes_from_xdr_buf(buf, base, &raw, sizeof(*obj));
@@ -903,9 +903,9 @@ out_seq:
 struct gss_svc_data {
        /* decoded gss client cred: */
        struct rpc_gss_wire_cred        clcred;
-       /* pointer to the beginning of the procedure-specific results,
-        * which may be encrypted/checksummed in svcauth_gss_release: */
-       u32                             *body_start;
+       /* save a pointer to the beginning of the encoded verifier,
+        * for use in encryption/checksumming in svcauth_gss_release: */
+       __be32                          *verf_start;
        struct rsc                      *rsci;
 };
 
@@ -946,7 +946,7 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
  * response here and return SVC_COMPLETE.
  */
 static int
-svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
+svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
 {
        struct kvec     *argv = &rqstp->rq_arg.head[0];
        struct kvec     *resv = &rqstp->rq_res.head[0];
@@ -956,8 +956,8 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
        struct rpc_gss_wire_cred *gc;
        struct rsc      *rsci = NULL;
        struct rsi      *rsip, rsikey;
-       u32             *rpcstart;
-       u32             *reject_stat = resv->iov_base + resv->iov_len;
+       __be32          *rpcstart;
+       __be32          *reject_stat = resv->iov_base + resv->iov_len;
        int             ret;
 
        dprintk("RPC:      svcauth_gss: argv->iov_len = %zd\n",argv->iov_len);
@@ -968,7 +968,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
        if (!svcdata)
                goto auth_err;
        rqstp->rq_auth_data = svcdata;
-       svcdata->body_start = NULL;
+       svcdata->verf_start = NULL;
        svcdata->rsci = NULL;
        gc = &svcdata->clcred;
 
@@ -1097,6 +1097,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                goto complete;
        case RPC_GSS_PROC_DATA:
                *authp = rpcsec_gsserr_ctxproblem;
+               svcdata->verf_start = resv->iov_base + resv->iov_len;
                if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
                        goto auth_err;
                rqstp->rq_cred = rsci->cred;
@@ -1110,7 +1111,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                                        gc->gc_seq, rsci->mechctx))
                                goto auth_err;
                        /* placeholders for length and seq. number: */
-                       svcdata->body_start = resv->iov_base + resv->iov_len;
                        svc_putnl(resv, 0);
                        svc_putnl(resv, 0);
                        break;
@@ -1119,7 +1119,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                                        gc->gc_seq, rsci->mechctx))
                                goto auth_err;
                        /* placeholders for length and seq. number: */
-                       svcdata->body_start = resv->iov_base + resv->iov_len;
                        svc_putnl(resv, 0);
                        svc_putnl(resv, 0);
                        break;
@@ -1147,6 +1146,32 @@ out:
        return ret;
 }
 
+u32 *
+svcauth_gss_prepare_to_wrap(struct xdr_buf *resbuf, struct gss_svc_data *gsd)
+{
+       u32 *p, verf_len;
+
+       p = gsd->verf_start;
+       gsd->verf_start = NULL;
+
+       /* If the reply stat is nonzero, don't wrap: */
+       if (*(p-1) != rpc_success)
+               return NULL;
+       /* Skip the verifier: */
+       p += 1;
+       verf_len = ntohl(*p++);
+       p += XDR_QUADLEN(verf_len);
+       /* move accept_stat to right place: */
+       memcpy(p, p + 2, 4);
+       /* Also don't wrap if the accept stat is nonzero: */
+       if (*p != rpc_success) {
+               resbuf->head[0].iov_len -= 2 * 4;
+               return NULL;
+       }
+       p++;
+       return p;
+}
+
 static inline int
 svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
 {
@@ -1156,21 +1181,13 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
        struct xdr_buf integ_buf;
        struct xdr_netobj mic;
        struct kvec *resv;
-       u32 *p;
+       __be32 *p;
        int integ_offset, integ_len;
        int stat = -EINVAL;
 
-       p = gsd->body_start;
-       gsd->body_start = NULL;
-       /* move accept_stat to right place: */
-       memcpy(p, p + 2, 4);
-       /* Don't wrap in failure case: */
-       /* Counting on not getting here if call was not even accepted! */
-       if (*p != rpc_success) {
-               resbuf->head[0].iov_len -= 2 * 4;
+       p = svcauth_gss_prepare_to_wrap(resbuf, gsd);
+       if (p == NULL)
                goto out;
-       }
-       p++;
        integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base;
        integ_len = resbuf->len - integ_offset;
        BUG_ON(integ_len % 4);
@@ -1191,7 +1208,6 @@ svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
                resbuf->tail[0].iov_base = resbuf->head[0].iov_base
                                                + resbuf->head[0].iov_len;
                resbuf->tail[0].iov_len = 0;
-               rqstp->rq_restailpage = 0;
                resv = &resbuf->tail[0];
        } else {
                resv = &resbuf->tail[0];
@@ -1219,28 +1235,20 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
        struct rpc_gss_wire_cred *gc = &gsd->clcred;
        struct xdr_buf *resbuf = &rqstp->rq_res;
        struct page **inpages = NULL;
-       u32 *p;
-       int offset, *len;
+       __be32 *p, *len;
+       int offset;
        int pad;
 
-       p = gsd->body_start;
-       gsd->body_start = NULL;
-       /* move accept_stat to right place: */
-       memcpy(p, p + 2, 4);
-       /* Don't wrap in failure case: */
-       /* Counting on not getting here if call was not even accepted! */
-       if (*p != rpc_success) {
-               resbuf->head[0].iov_len -= 2 * 4;
+       p = svcauth_gss_prepare_to_wrap(resbuf, gsd);
+       if (p == NULL)
                return 0;
-       }
-       p++;
        len = p++;
        offset = (u8 *)p - (u8 *)resbuf->head[0].iov_base;
        *p++ = htonl(gc->gc_seq);
        inpages = resbuf->pages;
        /* XXX: Would be better to write some xdr helper functions for
         * nfs{2,3,4}xdr.c that place the data right, instead of copying: */
-       if (resbuf->tail[0].iov_base && rqstp->rq_restailpage == 0) {
+       if (resbuf->tail[0].iov_base) {
                BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base
                                                        + PAGE_SIZE);
                BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base);
@@ -1258,13 +1266,12 @@ svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
                resbuf->tail[0].iov_base = resbuf->head[0].iov_base
                        + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE;
                resbuf->tail[0].iov_len = 0;
-               rqstp->rq_restailpage = 0;
        }
        if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages))
                return -ENOMEM;
        *len = htonl(resbuf->len - offset);
        pad = 3 - ((resbuf->len - offset - 1)&3);
-       p = (u32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
+       p = (__be32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
        memset(p, 0, pad);
        resbuf->tail[0].iov_len += pad;
        resbuf->len += pad;
@@ -1282,7 +1289,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
        if (gc->gc_proc != RPC_GSS_PROC_DATA)
                goto out;
        /* Release can be called twice, but we only wrap once. */
-       if (gsd->body_start == NULL)
+       if (gsd->verf_start == NULL)
                goto out;
        /* normally not set till svc_send, but we need it here: */
        /* XXX: what for?  Do we mess it up the moment we call svc_putu32