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>
This commit is contained in:

committed by
Trond Myklebust

parent
fb15b26f8b
commit
9568c5e9a6
@@ -134,33 +134,38 @@ static size_t nfs_parse_server_name(char *string, size_t len,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_find_best_sec - Find a security mechanism supported locally
|
||||
* @flavors: List of security tuples returned by SECINFO procedure
|
||||
*
|
||||
* Return the pseudoflavor of the first security mechanism in
|
||||
* "flavors" that is locally supported. Return RPC_AUTH_UNIX if
|
||||
* no matching flavor is found in the array. The "flavors" array
|
||||
* is searched in the order returned from the server, per RFC 3530
|
||||
* recommendation.
|
||||
*/
|
||||
rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
|
||||
{
|
||||
struct gss_api_mech *mech;
|
||||
struct xdr_netobj oid;
|
||||
rpc_authflavor_t pseudoflavor;
|
||||
struct nfs4_secinfo4 *secinfo;
|
||||
unsigned int i;
|
||||
rpc_authflavor_t pseudoflavor = RPC_AUTH_UNIX;
|
||||
|
||||
for (i = 0; i < flavors->num_flavors; i++) {
|
||||
struct nfs4_secinfo4 *flavor = &flavors->flavors[i];
|
||||
secinfo = &flavors->flavors[i];
|
||||
|
||||
if (flavor->flavor == RPC_AUTH_NULL || flavor->flavor == RPC_AUTH_UNIX) {
|
||||
pseudoflavor = flavor->flavor;
|
||||
break;
|
||||
} else if (flavor->flavor == RPC_AUTH_GSS) {
|
||||
oid.len = flavor->flavor_info.oid.len;
|
||||
oid.data = flavor->flavor_info.oid.data;
|
||||
mech = gss_mech_get_by_OID(&oid);
|
||||
if (!mech)
|
||||
continue;
|
||||
pseudoflavor = gss_svc_to_pseudoflavor(mech,
|
||||
flavor->flavor_info.service);
|
||||
gss_mech_put(mech);
|
||||
switch (secinfo->flavor) {
|
||||
case RPC_AUTH_NULL:
|
||||
case RPC_AUTH_UNIX:
|
||||
case RPC_AUTH_GSS:
|
||||
pseudoflavor = rpcauth_get_pseudoflavor(secinfo->flavor,
|
||||
&secinfo->flavor_info);
|
||||
if (pseudoflavor != RPC_AUTH_MAXFLAVOR)
|
||||
return pseudoflavor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pseudoflavor;
|
||||
return RPC_AUTH_UNIX;
|
||||
}
|
||||
|
||||
static rpc_authflavor_t nfs4_negotiate_security(struct inode *inode, struct qstr *name)
|
||||
|
Reference in New Issue
Block a user