mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
Merge branch 'rpcsec_gss-from_cel' into linux-next
* rpcsec_gss-from_cel: (21 commits) NFS: Retry SETCLIENTID with AUTH_SYS instead of AUTH_NONE NFSv4: Don't clear the machine cred when client establish returns EACCES NFSv4: Fix issues in nfs4_discover_server_trunking NFSv4: Fix the fallback to AUTH_NULL if krb5i is not available NFS: Use server-recommended security flavor by default (NFSv3) SUNRPC: Don't recognize RPC_AUTH_MAXFLAVOR NFS: Use "krb5i" to establish NFSv4 state whenever possible NFS: Try AUTH_UNIX when PUTROOTFH gets NFS4ERR_WRONGSEC NFS: Use static list of security flavors during root FH lookup recovery NFS: Avoid PUTROOTFH when managing leases NFS: Clean up nfs4_proc_get_rootfh NFS: Handle missing rpc.gssd when looking up root FH SUNRPC: Remove EXPORT_SYMBOL_GPL() from GSS mech switch SUNRPC: Make gss_mech_get() static SUNRPC: Refactor nfsd4_do_encode_secinfo() SUNRPC: Consider qop when looking up pseudoflavors SUNRPC: Load GSS kernel module by OID SUNRPC: Introduce rpcauth_get_pseudoflavor() SUNRPC: Define rpcsec_gss_info structure NFS: Remove unneeded forward declaration ...
This commit is contained in:
commit
bd1d421abc
17 changed files with 375 additions and 240 deletions
|
|
@ -3,6 +3,7 @@ config SUNRPC
|
|||
|
||||
config SUNRPC_GSS
|
||||
tristate
|
||||
select OID_REGISTRY
|
||||
|
||||
config SUNRPC_BACKCHANNEL
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size");
|
|||
|
||||
static u32
|
||||
pseudoflavor_to_flavor(u32 flavor) {
|
||||
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
||||
if (flavor > RPC_AUTH_MAXFLAVOR)
|
||||
return RPC_AUTH_GSS;
|
||||
return flavor;
|
||||
}
|
||||
|
|
@ -123,6 +123,79 @@ rpcauth_unregister(const struct rpc_authops *ops)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(rpcauth_unregister);
|
||||
|
||||
/**
|
||||
* rpcauth_get_pseudoflavor - check if security flavor is supported
|
||||
* @flavor: a security flavor
|
||||
* @info: a GSS mech OID, quality of protection, and service value
|
||||
*
|
||||
* Verifies that an appropriate kernel module is available or already loaded.
|
||||
* Returns an equivalent pseudoflavor, or RPC_AUTH_MAXFLAVOR if "flavor" is
|
||||
* not supported locally.
|
||||
*/
|
||||
rpc_authflavor_t
|
||||
rpcauth_get_pseudoflavor(rpc_authflavor_t flavor, struct rpcsec_gss_info *info)
|
||||
{
|
||||
const struct rpc_authops *ops;
|
||||
rpc_authflavor_t pseudoflavor;
|
||||
|
||||
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 RPC_AUTH_MAXFLAVOR;
|
||||
}
|
||||
spin_unlock(&rpc_authflavor_lock);
|
||||
|
||||
pseudoflavor = flavor;
|
||||
if (ops->info2flavor != NULL)
|
||||
pseudoflavor = ops->info2flavor(info);
|
||||
|
||||
module_put(ops->owner);
|
||||
return pseudoflavor;
|
||||
}
|
||||
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;
|
||||
|
||||
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
||||
return -EINVAL;
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1641,6 +1641,8 @@ static const struct rpc_authops authgss_ops = {
|
|||
.pipes_create = gss_pipes_dentries_create,
|
||||
.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 = {
|
||||
|
|
@ -1733,6 +1735,7 @@ static void __exit exit_rpcsec_gss(void)
|
|||
rcu_barrier(); /* Wait for completion of call_rcu()'s */
|
||||
}
|
||||
|
||||
MODULE_ALIAS("rpc-auth-6");
|
||||
MODULE_LICENSE("GPL");
|
||||
module_param_named(expired_cred_retry_delay,
|
||||
gss_expired_cred_retry_delay,
|
||||
|
|
|
|||
|
|
@ -729,16 +729,19 @@ static const struct gss_api_ops gss_kerberos_ops = {
|
|||
static struct pf_desc gss_kerberos_pfs[] = {
|
||||
[0] = {
|
||||
.pseudoflavor = RPC_AUTH_GSS_KRB5,
|
||||
.qop = GSS_C_QOP_DEFAULT,
|
||||
.service = RPC_GSS_SVC_NONE,
|
||||
.name = "krb5",
|
||||
},
|
||||
[1] = {
|
||||
.pseudoflavor = RPC_AUTH_GSS_KRB5I,
|
||||
.qop = GSS_C_QOP_DEFAULT,
|
||||
.service = RPC_GSS_SVC_INTEGRITY,
|
||||
.name = "krb5i",
|
||||
},
|
||||
[2] = {
|
||||
.pseudoflavor = RPC_AUTH_GSS_KRB5P,
|
||||
.qop = GSS_C_QOP_DEFAULT,
|
||||
.service = RPC_GSS_SVC_PRIVACY,
|
||||
.name = "krb5p",
|
||||
},
|
||||
|
|
@ -750,11 +753,12 @@ MODULE_ALIAS("rpc-auth-gss-krb5p");
|
|||
MODULE_ALIAS("rpc-auth-gss-390003");
|
||||
MODULE_ALIAS("rpc-auth-gss-390004");
|
||||
MODULE_ALIAS("rpc-auth-gss-390005");
|
||||
MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
|
||||
|
||||
static struct gss_api_mech gss_kerberos_mech = {
|
||||
.gm_name = "krb5",
|
||||
.gm_owner = THIS_MODULE,
|
||||
.gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"},
|
||||
.gm_oid = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
|
||||
.gm_ops = &gss_kerberos_ops,
|
||||
.gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
|
||||
.gm_pfs = gss_kerberos_pfs,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/oid_registry.h>
|
||||
#include <linux/sunrpc/msg_prot.h>
|
||||
#include <linux/sunrpc/gss_asn1.h>
|
||||
#include <linux/sunrpc/auth_gss.h>
|
||||
|
|
@ -102,8 +103,13 @@ out:
|
|||
return status;
|
||||
}
|
||||
|
||||
int
|
||||
gss_mech_register(struct gss_api_mech *gm)
|
||||
/**
|
||||
* gss_mech_register - register a GSS mechanism
|
||||
* @gm: GSS mechanism handle
|
||||
*
|
||||
* Returns zero if successful, or a negative errno.
|
||||
*/
|
||||
int gss_mech_register(struct gss_api_mech *gm)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
|
@ -116,11 +122,14 @@ gss_mech_register(struct gss_api_mech *gm)
|
|||
dprintk("RPC: registered gss mechanism %s\n", gm->gm_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_mech_register);
|
||||
|
||||
void
|
||||
gss_mech_unregister(struct gss_api_mech *gm)
|
||||
/**
|
||||
* gss_mech_unregister - release a GSS mechanism
|
||||
* @gm: GSS mechanism handle
|
||||
*
|
||||
*/
|
||||
void gss_mech_unregister(struct gss_api_mech *gm)
|
||||
{
|
||||
spin_lock(®istered_mechs_lock);
|
||||
list_del(&gm->gm_list);
|
||||
|
|
@ -128,18 +137,14 @@ gss_mech_unregister(struct gss_api_mech *gm)
|
|||
dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name);
|
||||
gss_mech_free(gm);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_mech_unregister);
|
||||
|
||||
struct gss_api_mech *
|
||||
gss_mech_get(struct gss_api_mech *gm)
|
||||
static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm)
|
||||
{
|
||||
__module_get(gm->gm_owner);
|
||||
return gm;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_mech_get);
|
||||
|
||||
static struct gss_api_mech *
|
||||
_gss_mech_get_by_name(const char *name)
|
||||
{
|
||||
|
|
@ -169,12 +174,16 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)
|
|||
}
|
||||
return gm;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
|
||||
|
||||
struct gss_api_mech *
|
||||
gss_mech_get_by_OID(struct xdr_netobj *obj)
|
||||
static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
|
||||
{
|
||||
struct gss_api_mech *pos, *gm = NULL;
|
||||
char buf[32];
|
||||
|
||||
if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0)
|
||||
return NULL;
|
||||
dprintk("RPC: %s(%s)\n", __func__, buf);
|
||||
request_module("rpc-auth-gss-%s", buf);
|
||||
|
||||
spin_lock(®istered_mechs_lock);
|
||||
list_for_each_entry(pos, ®istered_mechs, gm_list) {
|
||||
|
|
@ -188,11 +197,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj)
|
|||
}
|
||||
spin_unlock(®istered_mechs_lock);
|
||||
return gm;
|
||||
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_mech_get_by_OID);
|
||||
|
||||
static inline int
|
||||
mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
|
||||
{
|
||||
|
|
@ -237,8 +243,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
|
||||
|
|
@ -268,19 +272,82 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size)
|
|||
return i;
|
||||
}
|
||||
|
||||
u32
|
||||
gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service)
|
||||
/**
|
||||
* gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor
|
||||
* @gm: GSS mechanism handle
|
||||
* @qop: GSS quality-of-protection value
|
||||
* @service: GSS service value
|
||||
*
|
||||
* Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found.
|
||||
*/
|
||||
rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop,
|
||||
u32 service)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < gm->gm_pf_num; i++) {
|
||||
if (gm->gm_pfs[i].service == service) {
|
||||
if (gm->gm_pfs[i].qop == qop &&
|
||||
gm->gm_pfs[i].service == service) {
|
||||
return gm->gm_pfs[i].pseudoflavor;
|
||||
}
|
||||
}
|
||||
return RPC_AUTH_MAXFLAVOR; /* illegal value */
|
||||
return RPC_AUTH_MAXFLAVOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple
|
||||
* @info: a GSS mech OID, quality of protection, and service value
|
||||
*
|
||||
* Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is
|
||||
* not supported.
|
||||
*/
|
||||
rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info)
|
||||
{
|
||||
rpc_authflavor_t pseudoflavor;
|
||||
struct gss_api_mech *gm;
|
||||
|
||||
gm = gss_mech_get_by_OID(&info->oid);
|
||||
if (gm == NULL)
|
||||
return RPC_AUTH_MAXFLAVOR;
|
||||
|
||||
pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service);
|
||||
|
||||
gss_mech_put(gm);
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor);
|
||||
|
||||
u32
|
||||
gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
|
||||
|
|
@ -294,8 +361,6 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
|
|||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_pseudoflavor_to_service);
|
||||
|
||||
char *
|
||||
gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
|
||||
{
|
||||
|
|
@ -308,8 +373,6 @@ gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_service_to_auth_domain_name);
|
||||
|
||||
void
|
||||
gss_mech_put(struct gss_api_mech * gm)
|
||||
{
|
||||
|
|
@ -317,8 +380,6 @@ gss_mech_put(struct gss_api_mech * gm)
|
|||
module_put(gm->gm_owner);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(gss_mech_put);
|
||||
|
||||
/* The mech could probably be determined from the token instead, but it's just
|
||||
* as easy for now to pass it in. */
|
||||
int
|
||||
|
|
|
|||
|
|
@ -1216,7 +1216,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
|
|||
svcdata->rsci = rsci;
|
||||
cache_get(&rsci->h);
|
||||
rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
|
||||
rsci->mechctx->mech_type, gc->gc_svc);
|
||||
rsci->mechctx->mech_type,
|
||||
GSS_C_QOP_DEFAULT,
|
||||
gc->gc_svc);
|
||||
ret = SVC_OK;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue