aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/auth_gss.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c65
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;
57static const struct rpc_credops gss_credops; 57static const struct rpc_credops gss_credops;
58static const struct rpc_credops gss_nullops; 58static const struct rpc_credops gss_nullops;
59 59
60#define GSS_RETRY_EXPIRED 5
61static 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
352static void 355static void
356gss_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
373static void
353gss_upcall_callback(struct rpc_task *task) 374gss_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);
530out: 545out:
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task)
1123 return 0; 1138 return 0;
1124} 1139}
1125 1140
1141static 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
1587MODULE_LICENSE("GPL"); 1622MODULE_LICENSE("GPL");
1623module_param_named(expired_cred_retry_delay,
1624 gss_expired_cred_retry_delay,
1625 uint, 0644);
1626MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until "
1627 "the RPC engine retries an expired credential");
1628
1588module_init(init_rpcsec_gss) 1629module_init(init_rpcsec_gss)
1589module_exit(exit_rpcsec_gss) 1630module_exit(exit_rpcsec_gss)