aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 14:28:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 14:28:08 -0400
commit8728f986fe29d872dc5dc72941088eb9cb8bc723 (patch)
treeb0742c9c396bc8e4fddfbe1da57777270a803970 /net/sunrpc/auth_gss
parente72859b87f57826f41e07a87bbaed65ed1133f85 (diff)
parent721ccfb79b6f74f4052de70236d24047e73682d4 (diff)
Merge tag 'nfs-for-3.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes and cleanups from Trond Myklebust: - NLM: stable fix for NFSv2/v3 blocking locks - NFSv4.x: stable fixes for the delegation recall error handling code - NFSv4.x: Security flavour negotiation fixes and cleanups by Chuck Lever - SUNRPC: A number of RPCSEC_GSS fixes and cleanups also from Chuck - NFSv4.x assorted state management and reboot recovery bugfixes - NFSv4.1: In cases where we have already looked up a file, and hold a valid filehandle, use the new open-by-filehandle operation instead of opening by name. - Allow the NFSv4.1 callback thread to freeze - NFSv4.x: ensure that file unlock waits for readahead to complete - NFSv4.1: ensure that the RPC layer doesn't override the NFS session table size negotiation by limiting the number of slots. - NFSv4.x: Fix SETATTR spec compatibility issues * tag 'nfs-for-3.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (67 commits) NFSv4: Warn once about servers that incorrectly apply open mode to setattr NFSv4: Servers should only check SETATTR stateid open mode on size change NFSv4: Don't recheck permissions on open in case of recovery cached open NFSv4.1: Don't do a delegated open for NFS4_OPEN_CLAIM_DELEG_CUR_FH modes NFSv4.1: Use the more efficient open_noattr call for open-by-filehandle NFS: Retry SETCLIENTID with AUTH_SYS instead of AUTH_NONE NFSv4: Ensure that we clear the NFS_OPEN_STATE flag when appropriate LOCKD: Ensure that nlmclnt_block resets block->b_status after a server reboot NFSv4: Ensure the LOCK call cannot use the delegation stateid NFSv4: Use the open stateid if the delegation has the wrong mode nfs: Send atime and mtime as a 64bit value NFSv4: Record the OPEN create mode used in the nfs4_opendata structure NFSv4.1: Set the RPC_CLNT_CREATE_INFINITE_SLOTS flag for NFSv4.1 transports SUNRPC: Allow rpc_create() to request that TCP slots be unlimited SUNRPC: Fix a livelock problem in the xprt->backlog queue NFSv4: Fix handling of revoked delegations by setattr NFSv4 release the sequence id in the return on close case nfs: remove unnecessary check for NULL inode->i_flock from nfs_delegation_claim_locks NFS: Ensure that NFS file unlock waits for readahead to complete NFS: Add functionality to allow waiting on all outstanding reads to complete ...
Diffstat (limited to 'net/sunrpc/auth_gss')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c3
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c6
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c119
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c4
4 files changed, 101 insertions, 31 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 5257d2982ba5..51415b07174e 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1641,6 +1641,8 @@ 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,
1645 .flavor2info = gss_mech_flavor2info,
1644}; 1646};
1645 1647
1646static const struct rpc_credops gss_credops = { 1648static const struct rpc_credops gss_credops = {
@@ -1733,6 +1735,7 @@ static void __exit exit_rpcsec_gss(void)
1733 rcu_barrier(); /* Wait for completion of call_rcu()'s */ 1735 rcu_barrier(); /* Wait for completion of call_rcu()'s */
1734} 1736}
1735 1737
1738MODULE_ALIAS("rpc-auth-6");
1736MODULE_LICENSE("GPL"); 1739MODULE_LICENSE("GPL");
1737module_param_named(expired_cred_retry_delay, 1740module_param_named(expired_cred_retry_delay,
1738 gss_expired_cred_retry_delay, 1741 gss_expired_cred_retry_delay,
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index d3611f11a8df..33255ff889c0 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -729,16 +729,19 @@ static const struct gss_api_ops gss_kerberos_ops = {
729static struct pf_desc gss_kerberos_pfs[] = { 729static struct pf_desc gss_kerberos_pfs[] = {
730 [0] = { 730 [0] = {
731 .pseudoflavor = RPC_AUTH_GSS_KRB5, 731 .pseudoflavor = RPC_AUTH_GSS_KRB5,
732 .qop = GSS_C_QOP_DEFAULT,
732 .service = RPC_GSS_SVC_NONE, 733 .service = RPC_GSS_SVC_NONE,
733 .name = "krb5", 734 .name = "krb5",
734 }, 735 },
735 [1] = { 736 [1] = {
736 .pseudoflavor = RPC_AUTH_GSS_KRB5I, 737 .pseudoflavor = RPC_AUTH_GSS_KRB5I,
738 .qop = GSS_C_QOP_DEFAULT,
737 .service = RPC_GSS_SVC_INTEGRITY, 739 .service = RPC_GSS_SVC_INTEGRITY,
738 .name = "krb5i", 740 .name = "krb5i",
739 }, 741 },
740 [2] = { 742 [2] = {
741 .pseudoflavor = RPC_AUTH_GSS_KRB5P, 743 .pseudoflavor = RPC_AUTH_GSS_KRB5P,
744 .qop = GSS_C_QOP_DEFAULT,
742 .service = RPC_GSS_SVC_PRIVACY, 745 .service = RPC_GSS_SVC_PRIVACY,
743 .name = "krb5p", 746 .name = "krb5p",
744 }, 747 },
@@ -750,11 +753,12 @@ MODULE_ALIAS("rpc-auth-gss-krb5p");
750MODULE_ALIAS("rpc-auth-gss-390003"); 753MODULE_ALIAS("rpc-auth-gss-390003");
751MODULE_ALIAS("rpc-auth-gss-390004"); 754MODULE_ALIAS("rpc-auth-gss-390004");
752MODULE_ALIAS("rpc-auth-gss-390005"); 755MODULE_ALIAS("rpc-auth-gss-390005");
756MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2");
753 757
754static struct gss_api_mech gss_kerberos_mech = { 758static struct gss_api_mech gss_kerberos_mech = {
755 .gm_name = "krb5", 759 .gm_name = "krb5",
756 .gm_owner = THIS_MODULE, 760 .gm_owner = THIS_MODULE,
757 .gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}, 761 .gm_oid = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" },
758 .gm_ops = &gss_kerberos_ops, 762 .gm_ops = &gss_kerberos_ops,
759 .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), 763 .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
760 .gm_pfs = gss_kerberos_pfs, 764 .gm_pfs = gss_kerberos_pfs,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index f0f4eee63a35..79881d6e68a1 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -36,6 +36,7 @@
36#include <linux/types.h> 36#include <linux/types.h>
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/module.h> 38#include <linux/module.h>
39#include <linux/oid_registry.h>
39#include <linux/sunrpc/msg_prot.h> 40#include <linux/sunrpc/msg_prot.h>
40#include <linux/sunrpc/gss_asn1.h> 41#include <linux/sunrpc/gss_asn1.h>
41#include <linux/sunrpc/auth_gss.h> 42#include <linux/sunrpc/auth_gss.h>
@@ -102,8 +103,13 @@ out:
102 return status; 103 return status;
103} 104}
104 105
105int 106/**
106gss_mech_register(struct gss_api_mech *gm) 107 * gss_mech_register - register a GSS mechanism
108 * @gm: GSS mechanism handle
109 *
110 * Returns zero if successful, or a negative errno.
111 */
112int gss_mech_register(struct gss_api_mech *gm)
107{ 113{
108 int status; 114 int status;
109 115
@@ -116,11 +122,14 @@ gss_mech_register(struct gss_api_mech *gm)
116 dprintk("RPC: registered gss mechanism %s\n", gm->gm_name); 122 dprintk("RPC: registered gss mechanism %s\n", gm->gm_name);
117 return 0; 123 return 0;
118} 124}
119
120EXPORT_SYMBOL_GPL(gss_mech_register); 125EXPORT_SYMBOL_GPL(gss_mech_register);
121 126
122void 127/**
123gss_mech_unregister(struct gss_api_mech *gm) 128 * gss_mech_unregister - release a GSS mechanism
129 * @gm: GSS mechanism handle
130 *
131 */
132void gss_mech_unregister(struct gss_api_mech *gm)
124{ 133{
125 spin_lock(&registered_mechs_lock); 134 spin_lock(&registered_mechs_lock);
126 list_del(&gm->gm_list); 135 list_del(&gm->gm_list);
@@ -128,18 +137,14 @@ gss_mech_unregister(struct gss_api_mech *gm)
128 dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name); 137 dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name);
129 gss_mech_free(gm); 138 gss_mech_free(gm);
130} 139}
131
132EXPORT_SYMBOL_GPL(gss_mech_unregister); 140EXPORT_SYMBOL_GPL(gss_mech_unregister);
133 141
134struct gss_api_mech * 142static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm)
135gss_mech_get(struct gss_api_mech *gm)
136{ 143{
137 __module_get(gm->gm_owner); 144 __module_get(gm->gm_owner);
138 return gm; 145 return gm;
139} 146}
140 147
141EXPORT_SYMBOL_GPL(gss_mech_get);
142
143static struct gss_api_mech * 148static struct gss_api_mech *
144_gss_mech_get_by_name(const char *name) 149_gss_mech_get_by_name(const char *name)
145{ 150{
@@ -169,12 +174,16 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name)
169 } 174 }
170 return gm; 175 return gm;
171} 176}
172EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
173 177
174struct gss_api_mech * 178static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj)
175gss_mech_get_by_OID(struct xdr_netobj *obj)
176{ 179{
177 struct gss_api_mech *pos, *gm = NULL; 180 struct gss_api_mech *pos, *gm = NULL;
181 char buf[32];
182
183 if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0)
184 return NULL;
185 dprintk("RPC: %s(%s)\n", __func__, buf);
186 request_module("rpc-auth-gss-%s", buf);
178 187
179 spin_lock(&registered_mechs_lock); 188 spin_lock(&registered_mechs_lock);
180 list_for_each_entry(pos, &registered_mechs, gm_list) { 189 list_for_each_entry(pos, &registered_mechs, gm_list) {
@@ -188,11 +197,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj)
188 } 197 }
189 spin_unlock(&registered_mechs_lock); 198 spin_unlock(&registered_mechs_lock);
190 return gm; 199 return gm;
191
192} 200}
193 201
194EXPORT_SYMBOL_GPL(gss_mech_get_by_OID);
195
196static inline int 202static inline int
197mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) 203mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
198{ 204{
@@ -237,8 +243,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
237 return gm; 243 return gm;
238} 244}
239 245
240EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
241
242/** 246/**
243 * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors 247 * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors
244 * @array: array to fill in 248 * @array: array to fill in
@@ -268,19 +272,82 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size)
268 return i; 272 return i;
269} 273}
270 274
271u32 275/**
272gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) 276 * gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor
277 * @gm: GSS mechanism handle
278 * @qop: GSS quality-of-protection value
279 * @service: GSS service value
280 *
281 * Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found.
282 */
283rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop,
284 u32 service)
273{ 285{
274 int i; 286 int i;
275 287
276 for (i = 0; i < gm->gm_pf_num; i++) { 288 for (i = 0; i < gm->gm_pf_num; i++) {
277 if (gm->gm_pfs[i].service == service) { 289 if (gm->gm_pfs[i].qop == qop &&
290 gm->gm_pfs[i].service == service) {
278 return gm->gm_pfs[i].pseudoflavor; 291 return gm->gm_pfs[i].pseudoflavor;
279 } 292 }
280 } 293 }
281 return RPC_AUTH_MAXFLAVOR; /* illegal value */ 294 return RPC_AUTH_MAXFLAVOR;
295}
296
297/**
298 * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple
299 * @info: a GSS mech OID, quality of protection, and service value
300 *
301 * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is
302 * not supported.
303 */
304rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info)
305{
306 rpc_authflavor_t pseudoflavor;
307 struct gss_api_mech *gm;
308
309 gm = gss_mech_get_by_OID(&info->oid);
310 if (gm == NULL)
311 return RPC_AUTH_MAXFLAVOR;
312
313 pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service);
314
315 gss_mech_put(gm);
316 return pseudoflavor;
317}
318
319/**
320 * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor
321 * @pseudoflavor: GSS pseudoflavor to match
322 * @info: rpcsec_gss_info structure to fill in
323 *
324 * Returns zero and fills in "info" if pseudoflavor matches a
325 * supported mechanism. Otherwise a negative errno is returned.
326 */
327int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor,
328 struct rpcsec_gss_info *info)
329{
330 struct gss_api_mech *gm;
331 int i;
332
333 gm = gss_mech_get_by_pseudoflavor(pseudoflavor);
334 if (gm == NULL)
335 return -ENOENT;
336
337 for (i = 0; i < gm->gm_pf_num; i++) {
338 if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) {
339 memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len);
340 info->oid.len = gm->gm_oid.len;
341 info->qop = gm->gm_pfs[i].qop;
342 info->service = gm->gm_pfs[i].service;
343 gss_mech_put(gm);
344 return 0;
345 }
346 }
347
348 gss_mech_put(gm);
349 return -ENOENT;
282} 350}
283EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor);
284 351
285u32 352u32
286gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) 353gss_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)
294 return 0; 361 return 0;
295} 362}
296 363
297EXPORT_SYMBOL_GPL(gss_pseudoflavor_to_service);
298
299char * 364char *
300gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) 365gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
301{ 366{
@@ -308,8 +373,6 @@ gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
308 return NULL; 373 return NULL;
309} 374}
310 375
311EXPORT_SYMBOL_GPL(gss_service_to_auth_domain_name);
312
313void 376void
314gss_mech_put(struct gss_api_mech * gm) 377gss_mech_put(struct gss_api_mech * gm)
315{ 378{
@@ -317,8 +380,6 @@ gss_mech_put(struct gss_api_mech * gm)
317 module_put(gm->gm_owner); 380 module_put(gm->gm_owner);
318} 381}
319 382
320EXPORT_SYMBOL_GPL(gss_mech_put);
321
322/* The mech could probably be determined from the token instead, but it's just 383/* The mech could probably be determined from the token instead, but it's just
323 * as easy for now to pass it in. */ 384 * as easy for now to pass it in. */
324int 385int
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 5ead60550895..c3ba570222dc 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1220,7 +1220,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
1220 svcdata->rsci = rsci; 1220 svcdata->rsci = rsci;
1221 cache_get(&rsci->h); 1221 cache_get(&rsci->h);
1222 rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( 1222 rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
1223 rsci->mechctx->mech_type, gc->gc_svc); 1223 rsci->mechctx->mech_type,
1224 GSS_C_QOP_DEFAULT,
1225 gc->gc_svc);
1224 ret = SVC_OK; 1226 ret = SVC_OK;
1225 goto out; 1227 goto out;
1226 } 1228 }