diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2013-03-16 15:54:43 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-03-29 15:43:07 -0400 |
commit | 9568c5e9a61de49f67f524404a27a1014a8d7f1e (patch) | |
tree | 5bc8c5496bae61b6e5dfac11e620f7aef18a58b6 /net/sunrpc | |
parent | fb15b26f8ba3ff629a052faf3f4a4744585ca2dc (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.c | 35 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 1 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 28 |
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) | |||
124 | EXPORT_SYMBOL_GPL(rpcauth_unregister); | 124 | EXPORT_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 | */ | ||
135 | rpc_authflavor_t | ||
136 | rpcauth_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 | } | ||
159 | EXPORT_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 | ||
1646 | static const struct rpc_credops gss_credops = { | 1647 | 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 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 | } |
172 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); | 172 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); |
173 | 173 | ||
174 | struct gss_api_mech * | 174 | static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) |
175 | gss_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(®istered_mechs_lock); | 188 | spin_unlock(®istered_mechs_lock); |
190 | return gm; | 189 | return gm; |
191 | |||
192 | } | 190 | } |
193 | 191 | ||
194 | EXPORT_SYMBOL_GPL(gss_mech_get_by_OID); | ||
195 | |||
196 | static inline int | 192 | static inline int |
197 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) | 193 | mech_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 | } |
283 | EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor); | 279 | EXPORT_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 | */ | ||
288 | rpc_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 | |||
285 | u32 | 303 | u32 |
286 | gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) | 304 | gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) |
287 | { | 305 | { |