aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2013-03-16 15:54:43 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-03-29 15:43:07 -0400
commit9568c5e9a61de49f67f524404a27a1014a8d7f1e (patch)
tree5bc8c5496bae61b6e5dfac11e620f7aef18a58b6 /net/sunrpc
parentfb15b26f8ba3ff629a052faf3f4a4744585ca2dc (diff)
SUNRPC: Introduce rpcauth_get_pseudoflavor()
A SECINFO reply may contain flavors whose kernel module is not yet loaded by the client's kernel. A new RPC client API, called rpcauth_get_pseudoflavor(), is introduced to do proper checking for support of a security flavor. When this API is invoked, the RPC client now tries to load the module for each flavor first before performing the "is this supported?" check. This means if a module is available on the client, but has not been loaded yet, it will be loaded and registered automatically when the SECINFO reply is processed. The new API can take a full GSS tuple (OID, QoP, and service). Previously only the OID and service were considered. nfs_find_best_sec() is updated to verify all flavors requested in a SECINFO reply, including AUTH_NULL and AUTH_UNIX. Previously these two flavors were simply assumed to be supported without consulting the RPC client. Note that the replaced version of nfs_find_best_sec() can return RPC_AUTH_MAXFLAVOR if the server returns a recognized OID but an unsupported "service" value. nfs_find_best_sec() now returns RPC_AUTH_UNIX in this case. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth.c35
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c1
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c28
3 files changed, 59 insertions, 5 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index f5294047df77..9b81be8d9946 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -124,6 +124,41 @@ rpcauth_unregister(const struct rpc_authops *ops)
124EXPORT_SYMBOL_GPL(rpcauth_unregister); 124EXPORT_SYMBOL_GPL(rpcauth_unregister);
125 125
126/** 126/**
127 * rpcauth_get_pseudoflavor - check if security flavor is supported
128 * @flavor: a security flavor
129 * @info: a GSS mech OID, quality of protection, and service value
130 *
131 * Verifies that an appropriate kernel module is available or already loaded.
132 * Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is
133 * not supported locally.
134 */
135rpc_authflavor_t
136rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
137{
138 const struct rpc_authops *ops;
139 rpc_authflavor_t pseudoflavor;
140
141 ops = auth_flavors[flavor];
142 if (ops == NULL)
143 request_module("rpc-auth-%u", flavor);
144 spin_lock(&rpc_authflavor_lock);
145 ops = auth_flavors[flavor];
146 if (ops == NULL || !try_module_get(ops->owner)) {
147 spin_unlock(&rpc_authflavor_lock);
148 return RPC_AUTH_MAXFLAVOR;
149 }
150 spin_unlock(&rpc_authflavor_lock);
151
152 pseudoflavor = flavor;
153 if (ops->info2flavor != NULL)
154 pseudoflavor = ops->info2flavor(info);
155
156 module_put(ops->owner);
157 return pseudoflavor;
158}
159EXPORT_SYMBOL_GPL(rpcauth_get_pseudoflavor);
160
161/**
127 * rpcauth_list_flavors - discover registered flavors and pseudoflavors 162 * rpcauth_list_flavors - discover registered flavors and pseudoflavors
128 * @array: array to fill in 163 * @array: array to fill in
129 * @size: size of "array" 164 * @size: size of "array"
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 282dfb14db05..a7420076ef39 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1641,6 +1641,7 @@ static const struct rpc_authops authgss_ops = {
1641 .pipes_create = gss_pipes_dentries_create, 1641 .pipes_create = gss_pipes_dentries_create,
1642 .pipes_destroy = gss_pipes_dentries_destroy, 1642 .pipes_destroy = gss_pipes_dentries_destroy,
1643 .list_pseudoflavors = gss_mech_list_pseudoflavors, 1643 .list_pseudoflavors = gss_mech_list_pseudoflavors,
1644 .info2flavor = gss_mech_info2flavor,
1644}; 1645};
1645 1646
1646static const struct rpc_credops gss_credops = { 1647static 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 f0f4eee63a35..4db66f5f490e 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -171,8 +171,7 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)
171} 171}
172EXPORT_SYMBOL_GPL(gss_mech_get_by_name); 172EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
173 173
174struct gss_api_mech * 174static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
175gss_mech_get_by_OID(struct xdr_netobj *obj)
176{ 175{
177 struct gss_api_mech *pos, *gm = NULL; 176 struct gss_api_mech *pos, *gm = NULL;
178 177
@@ -188,11 +187,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj)
188 } 187 }
189 spin_unlock(&registered_mechs_lock); 188 spin_unlock(&registered_mechs_lock);
190 return gm; 189 return gm;
191
192} 190}
193 191
194EXPORT_SYMBOL_GPL(gss_mech_get_by_OID);
195
196static inline int 192static inline int
197mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) 193mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
198{ 194{
@@ -282,6 +278,28 @@ gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
282} 278}
283EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor); 279EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor);
284 280
281/**
282 * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple
283 * @info: a GSS mech OID, quality of protection, and service value
284 *
285 * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is
286 * not supported.
287 */
288rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info)
289{
290 rpc_authflavor_t pseudoflavor;
291 struct gss_api_mech *gm;
292
293 gm = gss_mech_get_by_OID(&info->oid);
294 if (gm == NULL)
295 return RPC_AUTH_MAXFLAVOR;
296
297 pseudoflavor = gss_svc_to_pseudoflavor(gm, info->service);
298
299 gss_mech_put(gm);
300 return pseudoflavor;
301}
302
285u32 303u32
286gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) 304gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
287{ 305{