mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
Merge branch 'nfs-for-next' of git://linux-nfs.org/~trondmy/nfs-2.6 into for-3.10
Note conflict: Chuck's patches modified (and made static) gss_mech_get_by_OID, which is still needed by gss-proxy patches. The conflict resolution is a bit minimal; we may want some more cleanup.
This commit is contained in:
commit
b1df763723
20 changed files with 456 additions and 277 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,
|
||||
|
|
|
|||
|
|
@ -732,16 +732,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",
|
||||
},
|
||||
|
|
@ -753,11 +756,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)
|
||||
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
|
||||
|
|
|
|||
|
|
@ -220,7 +220,6 @@ static int gssp_call(struct net *net, struct rpc_message *msg)
|
|||
|
||||
/* numbers somewhat arbitrary but large enough for current needs */
|
||||
#define GSSX_MAX_OUT_HANDLE 128
|
||||
#define GSSX_MAX_MECH_OID 16
|
||||
#define GSSX_MAX_SRC_PRINC 256
|
||||
#define GSSX_KMEMBUF (GSSX_max_output_handle_sz + \
|
||||
GSSX_max_oid_sz + \
|
||||
|
|
@ -242,7 +241,7 @@ int gssp_accept_sec_context_upcall(struct net *net,
|
|||
* buffers but let the xdr code kmalloc them:
|
||||
*/
|
||||
.exported_context_token.len = GSSX_max_output_handle_sz,
|
||||
.mech.len = GSSX_max_oid_sz,
|
||||
.mech.len = GSS_OID_MAX_LEN,
|
||||
.src_name.display_name.len = GSSX_max_princ_sz
|
||||
};
|
||||
struct gssx_res_accept_sec_context res = {
|
||||
|
|
@ -272,7 +271,9 @@ int gssp_accept_sec_context_upcall(struct net *net,
|
|||
data->minor_status = res.status.minor_status;
|
||||
if (res.context_handle) {
|
||||
data->out_handle = rctxh.exported_context_token;
|
||||
data->mech_oid = rctxh.mech;
|
||||
data->mech_oid.len = rctxh.mech.len;
|
||||
memcpy(data->mech_oid.data, rctxh.mech.data,
|
||||
data->mech_oid.len);
|
||||
client_name = rctxh.src_name.display_name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#ifndef _GSS_RPC_UPCALL_H
|
||||
#define _GSS_RPC_UPCALL_H
|
||||
|
||||
#include <linux/sunrpc/gss_api.h>
|
||||
#include <linux/sunrpc/auth_gss.h>
|
||||
#include "gss_rpc_xdr.h"
|
||||
#include "../netns.h"
|
||||
|
|
@ -30,7 +31,7 @@ struct gssp_upcall_data {
|
|||
struct gssp_in_token in_token;
|
||||
struct xdr_netobj out_handle;
|
||||
struct xdr_netobj out_token;
|
||||
struct xdr_netobj mech_oid;
|
||||
struct rpcsec_gss_oid mech_oid;
|
||||
struct svc_cred creds;
|
||||
int found_creds;
|
||||
int major_status;
|
||||
|
|
|
|||
|
|
@ -1544,7 +1544,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -304,10 +304,8 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru
|
|||
err = rpciod_up();
|
||||
if (err)
|
||||
goto out_no_rpciod;
|
||||
err = -EINVAL;
|
||||
if (!xprt)
|
||||
goto out_no_xprt;
|
||||
|
||||
err = -EINVAL;
|
||||
if (args->version >= program->nrvers)
|
||||
goto out_err;
|
||||
version = program->version[args->version];
|
||||
|
|
@ -382,10 +380,9 @@ out_no_principal:
|
|||
out_no_stats:
|
||||
kfree(clnt);
|
||||
out_err:
|
||||
xprt_put(xprt);
|
||||
out_no_xprt:
|
||||
rpciod_down();
|
||||
out_no_rpciod:
|
||||
xprt_put(xprt);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
|
@ -516,7 +513,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
|
|||
new = rpc_new_client(args, xprt);
|
||||
if (IS_ERR(new)) {
|
||||
err = PTR_ERR(new);
|
||||
goto out_put;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
atomic_inc(&clnt->cl_count);
|
||||
|
|
@ -529,8 +526,6 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
|
|||
new->cl_chatty = clnt->cl_chatty;
|
||||
return new;
|
||||
|
||||
out_put:
|
||||
xprt_put(xprt);
|
||||
out_err:
|
||||
dprintk("RPC: %s: returned error %d\n", __func__, err);
|
||||
return ERR_PTR(err);
|
||||
|
|
|
|||
Loading…
Reference in a new issue