diff options
Diffstat (limited to 'net/sunrpc/auth_gss/svcauth_gss.c')
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 182 |
1 files changed, 142 insertions, 40 deletions
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 23632d84d8d7..4d7eb9e704da 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -78,7 +78,8 @@ struct rsi { | |||
78 | 78 | ||
79 | static struct cache_head *rsi_table[RSI_HASHMAX]; | 79 | static struct cache_head *rsi_table[RSI_HASHMAX]; |
80 | static struct cache_detail rsi_cache; | 80 | static struct cache_detail rsi_cache; |
81 | static struct rsi *rsi_lookup(struct rsi *item, int set); | 81 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old); |
82 | static struct rsi *rsi_lookup(struct rsi *item); | ||
82 | 83 | ||
83 | static void rsi_free(struct rsi *rsii) | 84 | static void rsi_free(struct rsi *rsii) |
84 | { | 85 | { |
@@ -88,13 +89,11 @@ static void rsi_free(struct rsi *rsii) | |||
88 | kfree(rsii->out_token.data); | 89 | kfree(rsii->out_token.data); |
89 | } | 90 | } |
90 | 91 | ||
91 | static void rsi_put(struct cache_head *item, struct cache_detail *cd) | 92 | static void rsi_put(struct kref *ref) |
92 | { | 93 | { |
93 | struct rsi *rsii = container_of(item, struct rsi, h); | 94 | struct rsi *rsii = container_of(ref, struct rsi, h.ref); |
94 | if (cache_put(item, cd)) { | 95 | rsi_free(rsii); |
95 | rsi_free(rsii); | 96 | kfree(rsii); |
96 | kfree(rsii); | ||
97 | } | ||
98 | } | 97 | } |
99 | 98 | ||
100 | static inline int rsi_hash(struct rsi *item) | 99 | static inline int rsi_hash(struct rsi *item) |
@@ -103,8 +102,10 @@ static inline int rsi_hash(struct rsi *item) | |||
103 | ^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS); | 102 | ^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS); |
104 | } | 103 | } |
105 | 104 | ||
106 | static inline int rsi_match(struct rsi *item, struct rsi *tmp) | 105 | static int rsi_match(struct cache_head *a, struct cache_head *b) |
107 | { | 106 | { |
107 | struct rsi *item = container_of(a, struct rsi, h); | ||
108 | struct rsi *tmp = container_of(b, struct rsi, h); | ||
108 | return netobj_equal(&item->in_handle, &tmp->in_handle) | 109 | return netobj_equal(&item->in_handle, &tmp->in_handle) |
109 | && netobj_equal(&item->in_token, &tmp->in_token); | 110 | && netobj_equal(&item->in_token, &tmp->in_token); |
110 | } | 111 | } |
@@ -125,8 +126,11 @@ static inline int dup_netobj(struct xdr_netobj *dst, struct xdr_netobj *src) | |||
125 | return dup_to_netobj(dst, src->data, src->len); | 126 | return dup_to_netobj(dst, src->data, src->len); |
126 | } | 127 | } |
127 | 128 | ||
128 | static inline void rsi_init(struct rsi *new, struct rsi *item) | 129 | static void rsi_init(struct cache_head *cnew, struct cache_head *citem) |
129 | { | 130 | { |
131 | struct rsi *new = container_of(cnew, struct rsi, h); | ||
132 | struct rsi *item = container_of(citem, struct rsi, h); | ||
133 | |||
130 | new->out_handle.data = NULL; | 134 | new->out_handle.data = NULL; |
131 | new->out_handle.len = 0; | 135 | new->out_handle.len = 0; |
132 | new->out_token.data = NULL; | 136 | new->out_token.data = NULL; |
@@ -141,8 +145,11 @@ static inline void rsi_init(struct rsi *new, struct rsi *item) | |||
141 | item->in_token.data = NULL; | 145 | item->in_token.data = NULL; |
142 | } | 146 | } |
143 | 147 | ||
144 | static inline void rsi_update(struct rsi *new, struct rsi *item) | 148 | static void update_rsi(struct cache_head *cnew, struct cache_head *citem) |
145 | { | 149 | { |
150 | struct rsi *new = container_of(cnew, struct rsi, h); | ||
151 | struct rsi *item = container_of(citem, struct rsi, h); | ||
152 | |||
146 | BUG_ON(new->out_handle.data || new->out_token.data); | 153 | BUG_ON(new->out_handle.data || new->out_token.data); |
147 | new->out_handle.len = item->out_handle.len; | 154 | new->out_handle.len = item->out_handle.len; |
148 | item->out_handle.len = 0; | 155 | item->out_handle.len = 0; |
@@ -157,6 +164,15 @@ static inline void rsi_update(struct rsi *new, struct rsi *item) | |||
157 | new->minor_status = item->minor_status; | 164 | new->minor_status = item->minor_status; |
158 | } | 165 | } |
159 | 166 | ||
167 | static struct cache_head *rsi_alloc(void) | ||
168 | { | ||
169 | struct rsi *rsii = kmalloc(sizeof(*rsii), GFP_KERNEL); | ||
170 | if (rsii) | ||
171 | return &rsii->h; | ||
172 | else | ||
173 | return NULL; | ||
174 | } | ||
175 | |||
160 | static void rsi_request(struct cache_detail *cd, | 176 | static void rsi_request(struct cache_detail *cd, |
161 | struct cache_head *h, | 177 | struct cache_head *h, |
162 | char **bpp, int *blen) | 178 | char **bpp, int *blen) |
@@ -198,6 +214,10 @@ static int rsi_parse(struct cache_detail *cd, | |||
198 | if (dup_to_netobj(&rsii.in_token, buf, len)) | 214 | if (dup_to_netobj(&rsii.in_token, buf, len)) |
199 | goto out; | 215 | goto out; |
200 | 216 | ||
217 | rsip = rsi_lookup(&rsii); | ||
218 | if (!rsip) | ||
219 | goto out; | ||
220 | |||
201 | rsii.h.flags = 0; | 221 | rsii.h.flags = 0; |
202 | /* expiry */ | 222 | /* expiry */ |
203 | expiry = get_expiry(&mesg); | 223 | expiry = get_expiry(&mesg); |
@@ -240,12 +260,14 @@ static int rsi_parse(struct cache_detail *cd, | |||
240 | goto out; | 260 | goto out; |
241 | } | 261 | } |
242 | rsii.h.expiry_time = expiry; | 262 | rsii.h.expiry_time = expiry; |
243 | rsip = rsi_lookup(&rsii, 1); | 263 | rsip = rsi_update(&rsii, rsip); |
244 | status = 0; | 264 | status = 0; |
245 | out: | 265 | out: |
246 | rsi_free(&rsii); | 266 | rsi_free(&rsii); |
247 | if (rsip) | 267 | if (rsip) |
248 | rsi_put(&rsip->h, &rsi_cache); | 268 | cache_put(&rsip->h, &rsi_cache); |
269 | else | ||
270 | status = -ENOMEM; | ||
249 | return status; | 271 | return status; |
250 | } | 272 | } |
251 | 273 | ||
@@ -257,9 +279,37 @@ static struct cache_detail rsi_cache = { | |||
257 | .cache_put = rsi_put, | 279 | .cache_put = rsi_put, |
258 | .cache_request = rsi_request, | 280 | .cache_request = rsi_request, |
259 | .cache_parse = rsi_parse, | 281 | .cache_parse = rsi_parse, |
282 | .match = rsi_match, | ||
283 | .init = rsi_init, | ||
284 | .update = update_rsi, | ||
285 | .alloc = rsi_alloc, | ||
260 | }; | 286 | }; |
261 | 287 | ||
262 | static DefineSimpleCacheLookup(rsi, 0) | 288 | static struct rsi *rsi_lookup(struct rsi *item) |
289 | { | ||
290 | struct cache_head *ch; | ||
291 | int hash = rsi_hash(item); | ||
292 | |||
293 | ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash); | ||
294 | if (ch) | ||
295 | return container_of(ch, struct rsi, h); | ||
296 | else | ||
297 | return NULL; | ||
298 | } | ||
299 | |||
300 | static struct rsi *rsi_update(struct rsi *new, struct rsi *old) | ||
301 | { | ||
302 | struct cache_head *ch; | ||
303 | int hash = rsi_hash(new); | ||
304 | |||
305 | ch = sunrpc_cache_update(&rsi_cache, &new->h, | ||
306 | &old->h, hash); | ||
307 | if (ch) | ||
308 | return container_of(ch, struct rsi, h); | ||
309 | else | ||
310 | return NULL; | ||
311 | } | ||
312 | |||
263 | 313 | ||
264 | /* | 314 | /* |
265 | * The rpcsec_context cache is used to store a context that is | 315 | * The rpcsec_context cache is used to store a context that is |
@@ -293,7 +343,8 @@ struct rsc { | |||
293 | 343 | ||
294 | static struct cache_head *rsc_table[RSC_HASHMAX]; | 344 | static struct cache_head *rsc_table[RSC_HASHMAX]; |
295 | static struct cache_detail rsc_cache; | 345 | static struct cache_detail rsc_cache; |
296 | static struct rsc *rsc_lookup(struct rsc *item, int set); | 346 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old); |
347 | static struct rsc *rsc_lookup(struct rsc *item); | ||
297 | 348 | ||
298 | static void rsc_free(struct rsc *rsci) | 349 | static void rsc_free(struct rsc *rsci) |
299 | { | 350 | { |
@@ -304,14 +355,12 @@ static void rsc_free(struct rsc *rsci) | |||
304 | put_group_info(rsci->cred.cr_group_info); | 355 | put_group_info(rsci->cred.cr_group_info); |
305 | } | 356 | } |
306 | 357 | ||
307 | static void rsc_put(struct cache_head *item, struct cache_detail *cd) | 358 | static void rsc_put(struct kref *ref) |
308 | { | 359 | { |
309 | struct rsc *rsci = container_of(item, struct rsc, h); | 360 | struct rsc *rsci = container_of(ref, struct rsc, h.ref); |
310 | 361 | ||
311 | if (cache_put(item, cd)) { | 362 | rsc_free(rsci); |
312 | rsc_free(rsci); | 363 | kfree(rsci); |
313 | kfree(rsci); | ||
314 | } | ||
315 | } | 364 | } |
316 | 365 | ||
317 | static inline int | 366 | static inline int |
@@ -320,15 +369,21 @@ rsc_hash(struct rsc *rsci) | |||
320 | return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS); | 369 | return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS); |
321 | } | 370 | } |
322 | 371 | ||
323 | static inline int | 372 | static int |
324 | rsc_match(struct rsc *new, struct rsc *tmp) | 373 | rsc_match(struct cache_head *a, struct cache_head *b) |
325 | { | 374 | { |
375 | struct rsc *new = container_of(a, struct rsc, h); | ||
376 | struct rsc *tmp = container_of(b, struct rsc, h); | ||
377 | |||
326 | return netobj_equal(&new->handle, &tmp->handle); | 378 | return netobj_equal(&new->handle, &tmp->handle); |
327 | } | 379 | } |
328 | 380 | ||
329 | static inline void | 381 | static void |
330 | rsc_init(struct rsc *new, struct rsc *tmp) | 382 | rsc_init(struct cache_head *cnew, struct cache_head *ctmp) |
331 | { | 383 | { |
384 | struct rsc *new = container_of(cnew, struct rsc, h); | ||
385 | struct rsc *tmp = container_of(ctmp, struct rsc, h); | ||
386 | |||
332 | new->handle.len = tmp->handle.len; | 387 | new->handle.len = tmp->handle.len; |
333 | tmp->handle.len = 0; | 388 | tmp->handle.len = 0; |
334 | new->handle.data = tmp->handle.data; | 389 | new->handle.data = tmp->handle.data; |
@@ -337,9 +392,12 @@ rsc_init(struct rsc *new, struct rsc *tmp) | |||
337 | new->cred.cr_group_info = NULL; | 392 | new->cred.cr_group_info = NULL; |
338 | } | 393 | } |
339 | 394 | ||
340 | static inline void | 395 | static void |
341 | rsc_update(struct rsc *new, struct rsc *tmp) | 396 | update_rsc(struct cache_head *cnew, struct cache_head *ctmp) |
342 | { | 397 | { |
398 | struct rsc *new = container_of(cnew, struct rsc, h); | ||
399 | struct rsc *tmp = container_of(ctmp, struct rsc, h); | ||
400 | |||
343 | new->mechctx = tmp->mechctx; | 401 | new->mechctx = tmp->mechctx; |
344 | tmp->mechctx = NULL; | 402 | tmp->mechctx = NULL; |
345 | memset(&new->seqdata, 0, sizeof(new->seqdata)); | 403 | memset(&new->seqdata, 0, sizeof(new->seqdata)); |
@@ -348,6 +406,16 @@ rsc_update(struct rsc *new, struct rsc *tmp) | |||
348 | tmp->cred.cr_group_info = NULL; | 406 | tmp->cred.cr_group_info = NULL; |
349 | } | 407 | } |
350 | 408 | ||
409 | static struct cache_head * | ||
410 | rsc_alloc(void) | ||
411 | { | ||
412 | struct rsc *rsci = kmalloc(sizeof(*rsci), GFP_KERNEL); | ||
413 | if (rsci) | ||
414 | return &rsci->h; | ||
415 | else | ||
416 | return NULL; | ||
417 | } | ||
418 | |||
351 | static int rsc_parse(struct cache_detail *cd, | 419 | static int rsc_parse(struct cache_detail *cd, |
352 | char *mesg, int mlen) | 420 | char *mesg, int mlen) |
353 | { | 421 | { |
@@ -373,6 +441,10 @@ static int rsc_parse(struct cache_detail *cd, | |||
373 | if (expiry == 0) | 441 | if (expiry == 0) |
374 | goto out; | 442 | goto out; |
375 | 443 | ||
444 | rscp = rsc_lookup(&rsci); | ||
445 | if (!rscp) | ||
446 | goto out; | ||
447 | |||
376 | /* uid, or NEGATIVE */ | 448 | /* uid, or NEGATIVE */ |
377 | rv = get_int(&mesg, &rsci.cred.cr_uid); | 449 | rv = get_int(&mesg, &rsci.cred.cr_uid); |
378 | if (rv == -EINVAL) | 450 | if (rv == -EINVAL) |
@@ -428,12 +500,14 @@ static int rsc_parse(struct cache_detail *cd, | |||
428 | gss_mech_put(gm); | 500 | gss_mech_put(gm); |
429 | } | 501 | } |
430 | rsci.h.expiry_time = expiry; | 502 | rsci.h.expiry_time = expiry; |
431 | rscp = rsc_lookup(&rsci, 1); | 503 | rscp = rsc_update(&rsci, rscp); |
432 | status = 0; | 504 | status = 0; |
433 | out: | 505 | out: |
434 | rsc_free(&rsci); | 506 | rsc_free(&rsci); |
435 | if (rscp) | 507 | if (rscp) |
436 | rsc_put(&rscp->h, &rsc_cache); | 508 | cache_put(&rscp->h, &rsc_cache); |
509 | else | ||
510 | status = -ENOMEM; | ||
437 | return status; | 511 | return status; |
438 | } | 512 | } |
439 | 513 | ||
@@ -444,9 +518,37 @@ static struct cache_detail rsc_cache = { | |||
444 | .name = "auth.rpcsec.context", | 518 | .name = "auth.rpcsec.context", |
445 | .cache_put = rsc_put, | 519 | .cache_put = rsc_put, |
446 | .cache_parse = rsc_parse, | 520 | .cache_parse = rsc_parse, |
521 | .match = rsc_match, | ||
522 | .init = rsc_init, | ||
523 | .update = update_rsc, | ||
524 | .alloc = rsc_alloc, | ||
447 | }; | 525 | }; |
448 | 526 | ||
449 | static DefineSimpleCacheLookup(rsc, 0); | 527 | static struct rsc *rsc_lookup(struct rsc *item) |
528 | { | ||
529 | struct cache_head *ch; | ||
530 | int hash = rsc_hash(item); | ||
531 | |||
532 | ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash); | ||
533 | if (ch) | ||
534 | return container_of(ch, struct rsc, h); | ||
535 | else | ||
536 | return NULL; | ||
537 | } | ||
538 | |||
539 | static struct rsc *rsc_update(struct rsc *new, struct rsc *old) | ||
540 | { | ||
541 | struct cache_head *ch; | ||
542 | int hash = rsc_hash(new); | ||
543 | |||
544 | ch = sunrpc_cache_update(&rsc_cache, &new->h, | ||
545 | &old->h, hash); | ||
546 | if (ch) | ||
547 | return container_of(ch, struct rsc, h); | ||
548 | else | ||
549 | return NULL; | ||
550 | } | ||
551 | |||
450 | 552 | ||
451 | static struct rsc * | 553 | static struct rsc * |
452 | gss_svc_searchbyctx(struct xdr_netobj *handle) | 554 | gss_svc_searchbyctx(struct xdr_netobj *handle) |
@@ -457,7 +559,7 @@ gss_svc_searchbyctx(struct xdr_netobj *handle) | |||
457 | memset(&rsci, 0, sizeof(rsci)); | 559 | memset(&rsci, 0, sizeof(rsci)); |
458 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) | 560 | if (dup_to_netobj(&rsci.handle, handle->data, handle->len)) |
459 | return NULL; | 561 | return NULL; |
460 | found = rsc_lookup(&rsci, 0); | 562 | found = rsc_lookup(&rsci); |
461 | rsc_free(&rsci); | 563 | rsc_free(&rsci); |
462 | if (!found) | 564 | if (!found) |
463 | return NULL; | 565 | return NULL; |
@@ -645,6 +747,8 @@ find_gss_auth_domain(struct gss_ctx *ctx, u32 svc) | |||
645 | return auth_domain_find(name); | 747 | return auth_domain_find(name); |
646 | } | 748 | } |
647 | 749 | ||
750 | static struct auth_ops svcauthops_gss; | ||
751 | |||
648 | int | 752 | int |
649 | svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) | 753 | svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) |
650 | { | 754 | { |
@@ -655,20 +759,18 @@ svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name) | |||
655 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 759 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
656 | if (!new) | 760 | if (!new) |
657 | goto out; | 761 | goto out; |
658 | cache_init(&new->h.h); | 762 | kref_init(&new->h.ref); |
659 | new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); | 763 | new->h.name = kmalloc(strlen(name) + 1, GFP_KERNEL); |
660 | if (!new->h.name) | 764 | if (!new->h.name) |
661 | goto out_free_dom; | 765 | goto out_free_dom; |
662 | strcpy(new->h.name, name); | 766 | strcpy(new->h.name, name); |
663 | new->h.flavour = RPC_AUTH_GSS; | 767 | new->h.flavour = &svcauthops_gss; |
664 | new->pseudoflavor = pseudoflavor; | 768 | new->pseudoflavor = pseudoflavor; |
665 | new->h.h.expiry_time = NEVER; | ||
666 | 769 | ||
667 | test = auth_domain_lookup(&new->h, 1); | 770 | test = auth_domain_lookup(name, &new->h); |
668 | if (test == &new->h) { | 771 | if (test != &new->h) { /* XXX Duplicate registration? */ |
669 | BUG_ON(atomic_dec_and_test(&new->h.h.refcnt)); | ||
670 | } else { /* XXX Duplicate registration? */ | ||
671 | auth_domain_put(&new->h); | 772 | auth_domain_put(&new->h); |
773 | /* dangling ref-count... */ | ||
672 | goto out; | 774 | goto out; |
673 | } | 775 | } |
674 | return 0; | 776 | return 0; |
@@ -895,7 +997,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, u32 *authp) | |||
895 | goto drop; | 997 | goto drop; |
896 | } | 998 | } |
897 | 999 | ||
898 | rsip = rsi_lookup(&rsikey, 0); | 1000 | rsip = rsi_lookup(&rsikey); |
899 | rsi_free(&rsikey); | 1001 | rsi_free(&rsikey); |
900 | if (!rsip) { | 1002 | if (!rsip) { |
901 | goto drop; | 1003 | goto drop; |
@@ -970,7 +1072,7 @@ drop: | |||
970 | ret = SVC_DROP; | 1072 | ret = SVC_DROP; |
971 | out: | 1073 | out: |
972 | if (rsci) | 1074 | if (rsci) |
973 | rsc_put(&rsci->h, &rsc_cache); | 1075 | cache_put(&rsci->h, &rsc_cache); |
974 | return ret; | 1076 | return ret; |
975 | } | 1077 | } |
976 | 1078 | ||
@@ -1062,7 +1164,7 @@ out_err: | |||
1062 | put_group_info(rqstp->rq_cred.cr_group_info); | 1164 | put_group_info(rqstp->rq_cred.cr_group_info); |
1063 | rqstp->rq_cred.cr_group_info = NULL; | 1165 | rqstp->rq_cred.cr_group_info = NULL; |
1064 | if (gsd->rsci) | 1166 | if (gsd->rsci) |
1065 | rsc_put(&gsd->rsci->h, &rsc_cache); | 1167 | cache_put(&gsd->rsci->h, &rsc_cache); |
1066 | gsd->rsci = NULL; | 1168 | gsd->rsci = NULL; |
1067 | 1169 | ||
1068 | return stat; | 1170 | return stat; |