Merge branch 'for-3.5' of git://linux-nfs.org/~bfields/linux
[pandora-kernel.git] / net / sunrpc / auth_gss / svcauth_gss.c
index 28b62db..73e9573 100644 (file)
@@ -336,7 +336,6 @@ struct rsc {
        struct svc_cred         cred;
        struct gss_svc_seq_data seqdata;
        struct gss_ctx          *mechctx;
-       char                    *client_name;
 };
 
 static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old);
@@ -347,9 +346,7 @@ static void rsc_free(struct rsc *rsci)
        kfree(rsci->handle.data);
        if (rsci->mechctx)
                gss_delete_sec_context(&rsci->mechctx);
-       if (rsci->cred.cr_group_info)
-               put_group_info(rsci->cred.cr_group_info);
-       kfree(rsci->client_name);
+       free_svc_cred(&rsci->cred);
 }
 
 static void rsc_put(struct kref *ref)
@@ -387,7 +384,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
        tmp->handle.data = NULL;
        new->mechctx = NULL;
        new->cred.cr_group_info = NULL;
-       new->client_name = NULL;
+       new->cred.cr_principal = NULL;
 }
 
 static void
@@ -402,8 +399,8 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
        spin_lock_init(&new->seqdata.sd_lock);
        new->cred = tmp->cred;
        tmp->cred.cr_group_info = NULL;
-       new->client_name = tmp->client_name;
-       tmp->client_name = NULL;
+       new->cred.cr_principal = tmp->cred.cr_principal;
+       tmp->cred.cr_principal = NULL;
 }
 
 static struct cache_head *
@@ -501,8 +498,8 @@ static int rsc_parse(struct cache_detail *cd,
                /* get client name */
                len = qword_get(&mesg, buf, mlen);
                if (len > 0) {
-                       rsci.client_name = kstrdup(buf, GFP_KERNEL);
-                       if (!rsci.client_name)
+                       rsci.cred.cr_principal = kstrdup(buf, GFP_KERNEL);
+                       if (!rsci.cred.cr_principal)
                                goto out;
                }
 
@@ -932,16 +929,6 @@ struct gss_svc_data {
        struct rsc                      *rsci;
 };
 
-char *svc_gss_principal(struct svc_rqst *rqstp)
-{
-       struct gss_svc_data *gd = (struct gss_svc_data *)rqstp->rq_auth_data;
-
-       if (gd && gd->rsci)
-               return gd->rsci->client_name;
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(svc_gss_principal);
-
 static int
 svcauth_gss_set_client(struct svc_rqst *rqstp)
 {
@@ -969,16 +956,17 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
 }
 
 static inline int
-gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip)
+gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
+               struct xdr_netobj *out_handle, int *major_status)
 {
        struct rsc *rsci;
        int        rc;
 
-       if (rsip->major_status != GSS_S_COMPLETE)
+       if (*major_status != GSS_S_COMPLETE)
                return gss_write_null_verf(rqstp);
-       rsci = gss_svc_searchbyctx(cd, &rsip->out_handle);
+       rsci = gss_svc_searchbyctx(cd, out_handle);
        if (rsci == NULL) {
-               rsip->major_status = GSS_S_NO_CONTEXT;
+               *major_status = GSS_S_NO_CONTEXT;
                return gss_write_null_verf(rqstp);
        }
        rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
@@ -986,22 +974,13 @@ gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi
        return rc;
 }
 
-/*
- * Having read the cred already and found we're in the context
- * initiation case, read the verifier and initiate (or check the results
- * of) upcalls to userspace for help with context initiation.  If
- * the upcall results are available, write the verifier and result.
- * Otherwise, drop the request pending an answer to the upcall.
- */
-static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
-                       struct rpc_gss_wire_cred *gc, __be32 *authp)
+static inline int
+gss_read_verf(struct rpc_gss_wire_cred *gc,
+             struct kvec *argv, __be32 *authp,
+             struct xdr_netobj *in_handle,
+             struct xdr_netobj *in_token)
 {
-       struct kvec *argv = &rqstp->rq_arg.head[0];
-       struct kvec *resv = &rqstp->rq_res.head[0];
        struct xdr_netobj tmpobj;
-       struct rsi *rsip, rsikey;
-       int ret;
-       struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
 
        /* Read the verifier; should be NULL: */
        *authp = rpc_autherr_badverf;
@@ -1011,24 +990,67 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
                return SVC_DENIED;
        if (svc_getnl(argv) != 0)
                return SVC_DENIED;
-
        /* Martial context handle and token for upcall: */
        *authp = rpc_autherr_badcred;
        if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
                return SVC_DENIED;
-       memset(&rsikey, 0, sizeof(rsikey));
-       if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
+       if (dup_netobj(in_handle, &gc->gc_ctx))
                return SVC_CLOSE;
        *authp = rpc_autherr_badverf;
        if (svc_safe_getnetobj(argv, &tmpobj)) {
-               kfree(rsikey.in_handle.data);
+               kfree(in_handle->data);
                return SVC_DENIED;
        }
-       if (dup_netobj(&rsikey.in_token, &tmpobj)) {
-               kfree(rsikey.in_handle.data);
+       if (dup_netobj(in_token, &tmpobj)) {
+               kfree(in_handle->data);
                return SVC_CLOSE;
        }
 
+       return 0;
+}
+
+static inline int
+gss_write_resv(struct kvec *resv, size_t size_limit,
+              struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
+              int major_status, int minor_status)
+{
+       if (resv->iov_len + 4 > size_limit)
+               return -1;
+       svc_putnl(resv, RPC_SUCCESS);
+       if (svc_safe_putnetobj(resv, out_handle))
+               return -1;
+       if (resv->iov_len + 3 * 4 > size_limit)
+               return -1;
+       svc_putnl(resv, major_status);
+       svc_putnl(resv, minor_status);
+       svc_putnl(resv, GSS_SEQ_WIN);
+       if (svc_safe_putnetobj(resv, out_token))
+               return -1;
+       return 0;
+}
+
+/*
+ * Having read the cred already and found we're in the context
+ * initiation case, read the verifier and initiate (or check the results
+ * of) upcalls to userspace for help with context initiation.  If
+ * the upcall results are available, write the verifier and result.
+ * Otherwise, drop the request pending an answer to the upcall.
+ */
+static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
+                       struct rpc_gss_wire_cred *gc, __be32 *authp)
+{
+       struct kvec *argv = &rqstp->rq_arg.head[0];
+       struct kvec *resv = &rqstp->rq_res.head[0];
+       struct rsi *rsip, rsikey;
+       int ret;
+       struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id);
+
+       memset(&rsikey, 0, sizeof(rsikey));
+       ret = gss_read_verf(gc, argv, authp,
+                           &rsikey.in_handle, &rsikey.in_token);
+       if (ret)
+               return ret;
+
        /* Perform upcall, or find upcall result: */
        rsip = rsi_lookup(sn->rsi_cache, &rsikey);
        rsi_free(&rsikey);
@@ -1040,19 +1062,12 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
 
        ret = SVC_CLOSE;
        /* Got an answer to the upcall; use it: */
-       if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip))
-               goto out;
-       if (resv->iov_len + 4 > PAGE_SIZE)
+       if (gss_write_init_verf(sn->rsc_cache, rqstp,
+                               &rsip->out_handle, &rsip->major_status))
                goto out;
-       svc_putnl(resv, RPC_SUCCESS);
-       if (svc_safe_putnetobj(resv, &rsip->out_handle))
-               goto out;
-       if (resv->iov_len + 3 * 4 > PAGE_SIZE)
-               goto out;
-       svc_putnl(resv, rsip->major_status);
-       svc_putnl(resv, rsip->minor_status);
-       svc_putnl(resv, GSS_SEQ_WIN);
-       if (svc_safe_putnetobj(resv, &rsip->out_token))
+       if (gss_write_resv(resv, PAGE_SIZE,
+                          &rsip->out_handle, &rsip->out_token,
+                          rsip->major_status, rsip->minor_status))
                goto out;
 
        ret = SVC_COMPLETE;
@@ -1192,7 +1207,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                }
                svcdata->rsci = rsci;
                cache_get(&rsci->h);
-               rqstp->rq_flavor = gss_svc_to_pseudoflavor(
+               rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
                                        rsci->mechctx->mech_type, gc->gc_svc);
                ret = SVC_OK;
                goto out;