diff options
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 65 |
1 files changed, 53 insertions, 12 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 48a7939dc9e..8da2a0e6857 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -57,6 +57,9 @@ static const struct rpc_authops authgss_ops; | |||
57 | static const struct rpc_credops gss_credops; | 57 | static const struct rpc_credops gss_credops; |
58 | static const struct rpc_credops gss_nullops; | 58 | static const struct rpc_credops gss_nullops; |
59 | 59 | ||
60 | #define GSS_RETRY_EXPIRED 5 | ||
61 | static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; | ||
62 | |||
60 | #ifdef RPC_DEBUG | 63 | #ifdef RPC_DEBUG |
61 | # define RPCDBG_FACILITY RPCDBG_AUTH | 64 | # define RPCDBG_FACILITY RPCDBG_AUTH |
62 | #endif | 65 | #endif |
@@ -350,6 +353,24 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg) | |||
350 | } | 353 | } |
351 | 354 | ||
352 | static void | 355 | static void |
356 | gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg) | ||
357 | { | ||
358 | switch (gss_msg->msg.errno) { | ||
359 | case 0: | ||
360 | if (gss_msg->ctx == NULL) | ||
361 | break; | ||
362 | clear_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags); | ||
363 | gss_cred_set_ctx(&gss_cred->gc_base, gss_msg->ctx); | ||
364 | break; | ||
365 | case -EKEYEXPIRED: | ||
366 | set_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags); | ||
367 | } | ||
368 | gss_cred->gc_upcall_timestamp = jiffies; | ||
369 | gss_cred->gc_upcall = NULL; | ||
370 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); | ||
371 | } | ||
372 | |||
373 | static void | ||
353 | gss_upcall_callback(struct rpc_task *task) | 374 | gss_upcall_callback(struct rpc_task *task) |
354 | { | 375 | { |
355 | struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, | 376 | struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, |
@@ -358,13 +379,9 @@ gss_upcall_callback(struct rpc_task *task) | |||
358 | struct inode *inode = &gss_msg->inode->vfs_inode; | 379 | struct inode *inode = &gss_msg->inode->vfs_inode; |
359 | 380 | ||
360 | spin_lock(&inode->i_lock); | 381 | spin_lock(&inode->i_lock); |
361 | if (gss_msg->ctx) | 382 | gss_handle_downcall_result(gss_cred, gss_msg); |
362 | gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx); | ||
363 | else | ||
364 | task->tk_status = gss_msg->msg.errno; | ||
365 | gss_cred->gc_upcall = NULL; | ||
366 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); | ||
367 | spin_unlock(&inode->i_lock); | 383 | spin_unlock(&inode->i_lock); |
384 | task->tk_status = gss_msg->msg.errno; | ||
368 | gss_release_msg(gss_msg); | 385 | gss_release_msg(gss_msg); |
369 | } | 386 | } |
370 | 387 | ||
@@ -513,18 +530,16 @@ gss_refresh_upcall(struct rpc_task *task) | |||
513 | spin_lock(&inode->i_lock); | 530 | spin_lock(&inode->i_lock); |
514 | if (gss_cred->gc_upcall != NULL) | 531 | if (gss_cred->gc_upcall != NULL) |
515 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); | 532 | rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); |
516 | else if (gss_msg->ctx != NULL) { | 533 | else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) { |
517 | gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx); | ||
518 | gss_cred->gc_upcall = NULL; | ||
519 | rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno); | ||
520 | } else if (gss_msg->msg.errno >= 0) { | ||
521 | task->tk_timeout = 0; | 534 | task->tk_timeout = 0; |
522 | gss_cred->gc_upcall = gss_msg; | 535 | gss_cred->gc_upcall = gss_msg; |
523 | /* gss_upcall_callback will release the reference to gss_upcall_msg */ | 536 | /* gss_upcall_callback will release the reference to gss_upcall_msg */ |
524 | atomic_inc(&gss_msg->count); | 537 | atomic_inc(&gss_msg->count); |
525 | rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); | 538 | rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); |
526 | } else | 539 | } else { |
540 | gss_handle_downcall_result(gss_cred, gss_msg); | ||
527 | err = gss_msg->msg.errno; | 541 | err = gss_msg->msg.errno; |
542 | } | ||
528 | spin_unlock(&inode->i_lock); | 543 | spin_unlock(&inode->i_lock); |
529 | gss_release_msg(gss_msg); | 544 | gss_release_msg(gss_msg); |
530 | out: | 545 | out: |
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task) | |||
1123 | return 0; | 1138 | return 0; |
1124 | } | 1139 | } |
1125 | 1140 | ||
1141 | static int gss_cred_is_negative_entry(struct rpc_cred *cred) | ||
1142 | { | ||
1143 | if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) { | ||
1144 | unsigned long now = jiffies; | ||
1145 | unsigned long begin, expire; | ||
1146 | struct gss_cred *gss_cred; | ||
1147 | |||
1148 | gss_cred = container_of(cred, struct gss_cred, gc_base); | ||
1149 | begin = gss_cred->gc_upcall_timestamp; | ||
1150 | expire = begin + gss_expired_cred_retry_delay * HZ; | ||
1151 | |||
1152 | if (time_in_range_open(now, begin, expire)) | ||
1153 | return 1; | ||
1154 | } | ||
1155 | return 0; | ||
1156 | } | ||
1157 | |||
1126 | /* | 1158 | /* |
1127 | * Refresh credentials. XXX - finish | 1159 | * Refresh credentials. XXX - finish |
1128 | */ | 1160 | */ |
@@ -1132,6 +1164,9 @@ gss_refresh(struct rpc_task *task) | |||
1132 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1164 | struct rpc_cred *cred = task->tk_msg.rpc_cred; |
1133 | int ret = 0; | 1165 | int ret = 0; |
1134 | 1166 | ||
1167 | if (gss_cred_is_negative_entry(cred)) | ||
1168 | return -EKEYEXPIRED; | ||
1169 | |||
1135 | if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && | 1170 | if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && |
1136 | !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) { | 1171 | !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) { |
1137 | ret = gss_renew_cred(task); | 1172 | ret = gss_renew_cred(task); |
@@ -1585,5 +1620,11 @@ static void __exit exit_rpcsec_gss(void) | |||
1585 | } | 1620 | } |
1586 | 1621 | ||
1587 | MODULE_LICENSE("GPL"); | 1622 | MODULE_LICENSE("GPL"); |
1623 | module_param_named(expired_cred_retry_delay, | ||
1624 | gss_expired_cred_retry_delay, | ||
1625 | uint, 0644); | ||
1626 | MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " | ||
1627 | "the RPC engine retries an expired credential"); | ||
1628 | |||
1588 | module_init(init_rpcsec_gss) | 1629 | module_init(init_rpcsec_gss) |
1589 | module_exit(exit_rpcsec_gss) | 1630 | module_exit(exit_rpcsec_gss) |