linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / sunrpc / auth_gss / svcauth_gss.c
index 5c8fe3b..23632d8 100644 (file)
@@ -250,6 +250,7 @@ out:
 }
 
 static struct cache_detail rsi_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = RSI_HASHMAX,
        .hash_table     = rsi_table,
        .name           = "auth.rpcsec.init",
@@ -419,7 +420,8 @@ static int rsc_parse(struct cache_detail *cd,
                        gss_mech_put(gm);
                        goto out;
                }
-               if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
+               status = gss_import_sec_context(buf, len, gm, &rsci.mechctx);
+               if (status) {
                        gss_mech_put(gm);
                        goto out;
                }
@@ -436,6 +438,7 @@ out:
 }
 
 static struct cache_detail rsc_cache = {
+       .owner          = THIS_MODULE,
        .hash_size      = RSC_HASHMAX,
        .hash_table     = rsc_table,
        .name           = "auth.rpcsec.context",
@@ -564,8 +567,7 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
 
        if (rqstp->rq_deferred) /* skip verification of revisited request */
                return SVC_OK;
-       if (gss_verify_mic(ctx_id, &rpchdr, &checksum, NULL)
-                                                       != GSS_S_COMPLETE) {
+       if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
                *authp = rpcsec_gsserr_credproblem;
                return SVC_DENIED;
        }
@@ -584,6 +586,20 @@ gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
        return SVC_OK;
 }
 
+static int
+gss_write_null_verf(struct svc_rqst *rqstp)
+{
+       u32     *p;
+
+       svc_putu32(rqstp->rq_res.head, htonl(RPC_AUTH_NULL));
+       p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
+       /* don't really need to check if head->iov_len > PAGE_SIZE ... */
+       *p++ = 0;
+       if (!xdr_ressize_check(rqstp, p))
+               return -1;
+       return 0;
+}
+
 static int
 gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
 {
@@ -602,7 +618,7 @@ gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
        xdr_buf_from_iov(&iov, &verf_data);
        p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
        mic.data = (u8 *)(p + 1);
-       maj_stat = gss_get_mic(ctx_id, 0, &verf_data, &mic);
+       maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                return -1;
        *p++ = htonl(mic.len);
@@ -708,7 +724,7 @@ unwrap_integ_data(struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
                goto out;
        if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
                goto out;
-       maj_stat = gss_verify_mic(ctx, &integ_buf, &mic, NULL);
+       maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
        if (maj_stat != GSS_S_COMPLETE)
                goto out;
        if (ntohl(svc_getu32(&buf->head[0])) != seq)
@@ -740,6 +756,21 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
        return SVC_OK;
 }
 
+static inline int
+gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip)
+{
+       struct rsc *rsci;
+
+       if (rsip->major_status != GSS_S_COMPLETE)
+               return gss_write_null_verf(rqstp);
+       rsci = gss_svc_searchbyctx(&rsip->out_handle);
+       if (rsci == NULL) {
+               rsip->major_status = GSS_S_NO_CONTEXT;
+               return gss_write_null_verf(rqstp);
+       }
+       return gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
+}
+
 /*
  * Accept an rpcsec packet.
  * If context establishment, punt to user space
@@ -875,11 +906,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp)
                case -ENOENT:
                        goto drop;
                case 0:
-                       rsci = gss_svc_searchbyctx(&rsip->out_handle);
-                       if (!rsci) {
-                               goto drop;
-                       }
-                       if (gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN))
+                       if (gss_write_init_verf(rqstp, rsip))
                                goto drop;
                        if (resv->iov_len + 4 > PAGE_SIZE)
                                goto drop;
@@ -1010,7 +1037,7 @@ svcauth_gss_release(struct svc_rqst *rqstp)
                        resv = &resbuf->tail[0];
                }
                mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
-               if (gss_get_mic(gsd->rsci->mechctx, 0, &integ_buf, &mic))
+               if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
                        goto out_err;
                svc_putu32(resv, htonl(mic.len));
                memset(mic.data + mic.len, 0,
@@ -1074,7 +1101,9 @@ gss_svc_init(void)
 void
 gss_svc_shutdown(void)
 {
-       cache_unregister(&rsc_cache);
-       cache_unregister(&rsi_cache);
+       if (cache_unregister(&rsc_cache))
+               printk(KERN_ERR "auth_rpcgss: failed to unregister rsc cache\n");
+       if (cache_unregister(&rsi_cache))
+               printk(KERN_ERR "auth_rpcgss: failed to unregister rsi cache\n");
        svc_auth_unregister(RPC_AUTH_GSS);
 }