diff options
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 24 | ||||
| -rw-r--r-- | include/linux/sunrpc/auth.h | 4 | ||||
| -rw-r--r-- | include/linux/sunrpc/gss_api.h | 3 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 35 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 1 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 35 | 
6 files changed, 87 insertions, 15 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 01168865dd3..2a2745615b4 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -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); diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 6851da4cb41..0dd00f4f681 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -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 *); diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index 96e5a81a54d..fca23380e66 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -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 *); diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 9b81be8d994..2bc0cc2196e 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -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" diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index a7420076ef3..51415b07174 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -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 = { diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index 81fb6f3e242..deaa7ae81cd 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c @@ -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)  {  |