SUNRPC: Refactor nfsd4_do_encode_secinfo()
Chuck Lever [Sat, 16 Mar 2013 19:55:10 +0000 (15:55 -0400)]
Clean up.  This matches a similar API for the client side, and
keeps ULP fingers out the of the GSS mech switch.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Acked-by: J. Bruce Fields <bfields@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

fs/nfsd/nfs4xdr.c
include/linux/sunrpc/auth.h
include/linux/sunrpc/gss_api.h
net/sunrpc/auth.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_mech_switch.c

index 0116886..2a27456 100644 (file)
@@ -3138,10 +3138,9 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
 
 static __be32
 nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
-                        __be32 nfserr,struct svc_export *exp)
+                        __be32 nfserr, struct svc_export *exp)
 {
-       int i = 0;
-       u32 nflavs;
+       u32 i, nflavs;
        struct exp_flavor_info *flavs;
        struct exp_flavor_info def_flavs[2];
        __be32 *p;
@@ -3172,30 +3171,29 @@ nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
        WRITE32(nflavs);
        ADJUST_ARGS();
        for (i = 0; i < nflavs; i++) {
-               u32 flav = flavs[i].pseudoflavor;
-               struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
+               struct rpcsec_gss_info info;
 
-               if (gm) {
+               if (rpcauth_get_gssinfo(flavs[i].pseudoflavor, &info) == 0) {
                        RESERVE_SPACE(4);
                        WRITE32(RPC_AUTH_GSS);
                        ADJUST_ARGS();
-                       RESERVE_SPACE(4 + gm->gm_oid.len);
-                       WRITE32(gm->gm_oid.len);
-                       WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
+                       RESERVE_SPACE(4 + info.oid.len);
+                       WRITE32(info.oid.len);
+                       WRITEMEM(info.oid.data, info.oid.len);
                        ADJUST_ARGS();
                        RESERVE_SPACE(4);
-                       WRITE32(0); /* qop */
+                       WRITE32(info.qop);
                        ADJUST_ARGS();
                        RESERVE_SPACE(4);
-                       WRITE32(gss_pseudoflavor_to_service(gm, flav));
+                       WRITE32(info.service);
                        ADJUST_ARGS();
-                       gss_mech_put(gm);
                } else {
                        RESERVE_SPACE(4);
-                       WRITE32(flav);
+                       WRITE32(flavs[i].pseudoflavor);
                        ADJUST_ARGS();
                }
        }
+
 out:
        if (exp)
                exp_put(exp);
index 6851da4..0dd00f4 100644 (file)
@@ -106,6 +106,8 @@ struct rpc_authops {
        void                    (*pipes_destroy)(struct rpc_auth *);
        int                     (*list_pseudoflavors)(rpc_authflavor_t *, int);
        rpc_authflavor_t        (*info2flavor)(struct rpcsec_gss_info *);
+       int                     (*flavor2info)(rpc_authflavor_t,
+                                               struct rpcsec_gss_info *);
 };
 
 struct rpc_credops {
@@ -142,6 +144,8 @@ struct rpc_auth *   rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
 void                   rpcauth_release(struct rpc_auth *);
 rpc_authflavor_t       rpcauth_get_pseudoflavor(rpc_authflavor_t,
                                struct rpcsec_gss_info *);
+int                    rpcauth_get_gssinfo(rpc_authflavor_t,
+                               struct rpcsec_gss_info *);
 int                    rpcauth_list_flavors(rpc_authflavor_t *, int);
 struct rpc_cred *      rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
 void                   rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
index 96e5a81..fca2338 100644 (file)
@@ -133,6 +133,9 @@ void gss_mech_unregister(struct gss_api_mech *);
 /* Given a GSS security tuple, look up a pseudoflavor */
 rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *);
 
+/* Given a pseudoflavor, look up a GSS security tuple */
+int gss_mech_flavor2info(rpc_authflavor_t, struct rpcsec_gss_info *);
+
 /* Returns a reference to a mechanism, given a name like "krb5" etc. */
 struct gss_api_mech *gss_mech_get_by_name(const char *);
 
index 9b81be8..2bc0cc2 100644 (file)
@@ -159,6 +159,41 @@ rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
 EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
 
 /**
+ * rpcauth_get_gssinfo - find GSS tuple matching a GSS pseudoflavor
+ * @pseudoflavor: GSS pseudoflavor to match
+ * @info: rpcsec_gss_info structure to fill in
+ *
+ * Returns zero and fills in "info" if pseudoflavor matches a
+ * supported mechanism.
+ */
+int
+rpcauth_get_gssinfo(rpc_authflavor_t pseudoflavor, struct rpcsec_gss_info *info)
+{
+       rpc_authflavor_t flavor = pseudoflavor_to_flavor(pseudoflavor);
+       const struct rpc_authops *ops;
+       int result;
+
+       ops = auth_flavors[flavor];
+       if (ops == NULL)
+               request_module("rpc-auth-%u", flavor);
+       spin_lock(&rpc_authflavor_lock);
+       ops = auth_flavors[flavor];
+       if (ops == NULL || !try_module_get(ops->owner)) {
+               spin_unlock(&rpc_authflavor_lock);
+               return -ENOENT;
+       }
+       spin_unlock(&rpc_authflavor_lock);
+
+       result = -ENOENT;
+       if (ops->flavor2info != NULL)
+               result = ops->flavor2info(pseudoflavor, info);
+
+       module_put(ops->owner);
+       return result;
+}
+EXPORT_SYMBOL_GPL(rpcauth_get_gssinfo);
+
+/**
  * rpcauth_list_flavors - discover registered flavors and pseudoflavors
  * @array: array to fill in
  * @size: size of "array"
index a742007..51415b0 100644 (file)
@@ -1642,6 +1642,7 @@ static const struct rpc_authops authgss_ops = {
        .pipes_destroy  = gss_pipes_dentries_destroy,
        .list_pseudoflavors = gss_mech_list_pseudoflavors,
        .info2flavor    = gss_mech_info2flavor,
+       .flavor2info    = gss_mech_flavor2info,
 };
 
 static const struct rpc_credops gss_credops = {
index 81fb6f3..deaa7ae 100644 (file)
@@ -240,8 +240,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
        return gm;
 }
 
-EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
-
 /**
  * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors
  * @array: array to fill in
@@ -315,6 +313,39 @@ rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info)
        return pseudoflavor;
 }
 
+/**
+ * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor
+ * @pseudoflavor: GSS pseudoflavor to match
+ * @info: rpcsec_gss_info structure to fill in
+ *
+ * Returns zero and fills in "info" if pseudoflavor matches a
+ * supported mechanism.  Otherwise a negative errno is returned.
+ */
+int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor,
+                        struct rpcsec_gss_info *info)
+{
+       struct gss_api_mech *gm;
+       int i;
+
+       gm = gss_mech_get_by_pseudoflavor(pseudoflavor);
+       if (gm == NULL)
+               return -ENOENT;
+
+       for (i = 0; i < gm->gm_pf_num; i++) {
+               if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) {
+                       memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len);
+                       info->oid.len = gm->gm_oid.len;
+                       info->qop = gm->gm_pfs[i].qop;
+                       info->service = gm->gm_pfs[i].service;
+                       gss_mech_put(gm);
+                       return 0;
+               }
+       }
+
+       gss_mech_put(gm);
+       return -ENOENT;
+}
+
 u32
 gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
 {