diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2012-07-11 16:31:08 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-07-16 15:12:15 -0400 |
commit | 6a1a1e34dc55f17e7bd260809207442dbb7a0296 (patch) | |
tree | 3a2ce5b9d3c8edc80f6486efc1f9b34cee559f8f | |
parent | 56d08fef2369d5ca9ad2e1fc697f5379fd8af751 (diff) |
SUNRPC: Add rpcauth_list_flavors()
The gss_mech_list_pseudoflavors() function provides a list of
currently registered GSS pseudoflavors. This list does not include
any non-GSS flavors that have been registered with the RPC client.
nfs4_find_root_sec() currently adds these extra flavors by hand.
Instead, nfs4_find_root_sec() should be looking at the set of flavors
that have been explicitly registered via rpcauth_register(). And,
other areas of code will soon need the same kind of list that
contains all flavors the kernel currently knows about (see below).
Rather than cloning the open-coded logic in nfs4_find_root_sec() to
those new places, introduce a generic RPC function that generates a
full list of registered auth flavors and pseudoflavors.
A new rpc_authops method is added that lists a flavor's
pseudoflavors, if it has any. I encountered an interesting module
loader loop when I tried to get the RPC client to invoke
gss_mech_list_pseudoflavors() by name.
This patch is a pre-requisite for server trunking discovery, and a
pre-requisite for fixing up the in-kernel mount client to do better
automatic security flavor selection.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/nfs4proc.c | 11 | ||||
-rw-r--r-- | include/linux/sunrpc/auth.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/gss_api.h | 3 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 54 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 1 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 18 |
6 files changed, 80 insertions, 9 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 31369e9b5b04..80bb5055d0b3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #include <linux/printk.h> | 43 | #include <linux/printk.h> |
44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
45 | #include <linux/sunrpc/clnt.h> | 45 | #include <linux/sunrpc/clnt.h> |
46 | #include <linux/sunrpc/gss_api.h> | ||
47 | #include <linux/nfs.h> | 46 | #include <linux/nfs.h> |
48 | #include <linux/nfs4.h> | 47 | #include <linux/nfs4.h> |
49 | #include <linux/nfs_fs.h> | 48 | #include <linux/nfs_fs.h> |
@@ -2412,11 +2411,15 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2412 | int i, len, status = 0; | 2411 | int i, len, status = 0; |
2413 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; | 2412 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; |
2414 | 2413 | ||
2415 | len = gss_mech_list_pseudoflavors(&flav_array[0]); | 2414 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); |
2416 | flav_array[len] = RPC_AUTH_NULL; | 2415 | BUG_ON(len < 0); |
2417 | len += 1; | ||
2418 | 2416 | ||
2419 | for (i = 0; i < len; i++) { | 2417 | for (i = 0; i < len; i++) { |
2418 | /* AUTH_UNIX is the default flavor if none was specified, | ||
2419 | * thus has already been tried. */ | ||
2420 | if (flav_array[i] == RPC_AUTH_UNIX) | ||
2421 | continue; | ||
2422 | |||
2420 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | 2423 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); |
2421 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) | 2424 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) |
2422 | continue; | 2425 | continue; |
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 492a36d72829..f25ba922baaf 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -101,6 +101,7 @@ struct rpc_authops { | |||
101 | struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); | 101 | struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); |
102 | int (*pipes_create)(struct rpc_auth *); | 102 | int (*pipes_create)(struct rpc_auth *); |
103 | void (*pipes_destroy)(struct rpc_auth *); | 103 | void (*pipes_destroy)(struct rpc_auth *); |
104 | int (*list_pseudoflavors)(rpc_authflavor_t *, int); | ||
104 | }; | 105 | }; |
105 | 106 | ||
106 | struct rpc_credops { | 107 | struct rpc_credops { |
@@ -135,6 +136,7 @@ int rpcauth_register(const struct rpc_authops *); | |||
135 | int rpcauth_unregister(const struct rpc_authops *); | 136 | int rpcauth_unregister(const struct rpc_authops *); |
136 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); | 137 | struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); |
137 | void rpcauth_release(struct rpc_auth *); | 138 | void rpcauth_release(struct rpc_auth *); |
139 | int rpcauth_list_flavors(rpc_authflavor_t *, int); | ||
138 | struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int); | 140 | struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int); |
139 | void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); | 141 | void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); |
140 | struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); | 142 | struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); |
diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index 332da61cf8b7..a19e2547ae6a 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #ifdef __KERNEL__ | 15 | #ifdef __KERNEL__ |
16 | #include <linux/sunrpc/xdr.h> | 16 | #include <linux/sunrpc/xdr.h> |
17 | #include <linux/sunrpc/msg_prot.h> | ||
17 | #include <linux/uio.h> | 18 | #include <linux/uio.h> |
18 | 19 | ||
19 | /* The mechanism-independent gss-api context: */ | 20 | /* The mechanism-independent gss-api context: */ |
@@ -127,7 +128,7 @@ struct gss_api_mech *gss_mech_get_by_name(const char *); | |||
127 | struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32); | 128 | struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32); |
128 | 129 | ||
129 | /* Fill in an array with a list of supported pseudoflavors */ | 130 | /* Fill in an array with a list of supported pseudoflavors */ |
130 | int gss_mech_list_pseudoflavors(u32 *); | 131 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *, int); |
131 | 132 | ||
132 | /* Just increments the mechanism's reference count and returns its input: */ | 133 | /* Just increments the mechanism's reference count and returns its input: */ |
133 | struct gss_api_mech * gss_mech_get(struct gss_api_mech *); | 134 | struct gss_api_mech * gss_mech_get(struct gss_api_mech *); |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 727e506cacda..b5c067bccc45 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
14 | #include <linux/hash.h> | 14 | #include <linux/hash.h> |
15 | #include <linux/sunrpc/clnt.h> | 15 | #include <linux/sunrpc/clnt.h> |
16 | #include <linux/sunrpc/gss_api.h> | ||
16 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
17 | 18 | ||
18 | #ifdef RPC_DEBUG | 19 | #ifdef RPC_DEBUG |
@@ -122,6 +123,59 @@ rpcauth_unregister(const struct rpc_authops *ops) | |||
122 | } | 123 | } |
123 | EXPORT_SYMBOL_GPL(rpcauth_unregister); | 124 | EXPORT_SYMBOL_GPL(rpcauth_unregister); |
124 | 125 | ||
126 | /** | ||
127 | * rpcauth_list_flavors - discover registered flavors and pseudoflavors | ||
128 | * @array: array to fill in | ||
129 | * @size: size of "array" | ||
130 | * | ||
131 | * Returns the number of array items filled in, or a negative errno. | ||
132 | * | ||
133 | * The returned array is not sorted by any policy. Callers should not | ||
134 | * rely on the order of the items in the returned array. | ||
135 | */ | ||
136 | int | ||
137 | rpcauth_list_flavors(rpc_authflavor_t *array, int size) | ||
138 | { | ||
139 | rpc_authflavor_t flavor; | ||
140 | int result = 0; | ||
141 | |||
142 | spin_lock(&rpc_authflavor_lock); | ||
143 | for (flavor = 0; flavor < RPC_AUTH_MAXFLAVOR; flavor++) { | ||
144 | const struct rpc_authops *ops = auth_flavors[flavor]; | ||
145 | rpc_authflavor_t pseudos[4]; | ||
146 | int i, len; | ||
147 | |||
148 | if (result >= size) { | ||
149 | result = -ENOMEM; | ||
150 | break; | ||
151 | } | ||
152 | |||
153 | if (ops == NULL) | ||
154 | continue; | ||
155 | if (ops->list_pseudoflavors == NULL) { | ||
156 | array[result++] = ops->au_flavor; | ||
157 | continue; | ||
158 | } | ||
159 | len = ops->list_pseudoflavors(pseudos, ARRAY_SIZE(pseudos)); | ||
160 | if (len < 0) { | ||
161 | result = len; | ||
162 | break; | ||
163 | } | ||
164 | for (i = 0; i < len; i++) { | ||
165 | if (result >= size) { | ||
166 | result = -ENOMEM; | ||
167 | break; | ||
168 | } | ||
169 | array[result++] = pseudos[i]; | ||
170 | } | ||
171 | } | ||
172 | spin_unlock(&rpc_authflavor_lock); | ||
173 | |||
174 | dprintk("RPC: %s returns %d\n", __func__, result); | ||
175 | return result; | ||
176 | } | ||
177 | EXPORT_SYMBOL_GPL(rpcauth_list_flavors); | ||
178 | |||
125 | struct rpc_auth * | 179 | struct rpc_auth * |
126 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) | 180 | rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) |
127 | { | 181 | { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d3ad81f8da5b..34c522021004 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1619,6 +1619,7 @@ static const struct rpc_authops authgss_ops = { | |||
1619 | .crcreate = gss_create_cred, | 1619 | .crcreate = gss_create_cred, |
1620 | .pipes_create = gss_pipes_dentries_create, | 1620 | .pipes_create = gss_pipes_dentries_create, |
1621 | .pipes_destroy = gss_pipes_dentries_destroy, | 1621 | .pipes_destroy = gss_pipes_dentries_destroy, |
1622 | .list_pseudoflavors = gss_mech_list_pseudoflavors, | ||
1622 | }; | 1623 | }; |
1623 | 1624 | ||
1624 | static const struct rpc_credops gss_credops = { | 1625 | 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 782bfe1b6465..6ac5dfcd2928 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -239,14 +239,26 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | |||
239 | 239 | ||
240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); | 240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); |
241 | 241 | ||
242 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) | 242 | /** |
243 | * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors | ||
244 | * @array: array to fill in | ||
245 | * @size: size of "array" | ||
246 | * | ||
247 | * Returns the number of array items filled in, or a negative errno. | ||
248 | * | ||
249 | * The returned array is not sorted by any policy. Callers should not | ||
250 | * rely on the order of the items in the returned array. | ||
251 | */ | ||
252 | int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size) | ||
243 | { | 253 | { |
244 | struct gss_api_mech *pos = NULL; | 254 | struct gss_api_mech *pos = NULL; |
245 | int j, i = 0; | 255 | int j, i = 0; |
246 | 256 | ||
247 | spin_lock(®istered_mechs_lock); | 257 | spin_lock(®istered_mechs_lock); |
248 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | 258 | list_for_each_entry(pos, ®istered_mechs, gm_list) { |
249 | for (j=0; j < pos->gm_pf_num; j++) { | 259 | for (j = 0; j < pos->gm_pf_num; j++) { |
260 | if (i >= size) | ||
261 | return -ENOMEM; | ||
250 | array_ptr[i++] = pos->gm_pfs[j].pseudoflavor; | 262 | array_ptr[i++] = pos->gm_pfs[j].pseudoflavor; |
251 | } | 263 | } |
252 | } | 264 | } |
@@ -254,8 +266,6 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) | |||
254 | return i; | 266 | return i; |
255 | } | 267 | } |
256 | 268 | ||
257 | EXPORT_SYMBOL_GPL(gss_mech_list_pseudoflavors); | ||
258 | |||
259 | u32 | 269 | u32 |
260 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) | 270 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) |
261 | { | 271 | { |